Parameter with non-deduced type after parameter pack
Asked Answered
G

1

4

There is different behaviour in clang++ and g++ for the next program:

#include <type_traits>
#include <utility>

template< std::size_t index, typename type >
struct ref { type & value; };

template< std::size_t index, typename type >
type && get(ref< index, type > const & r)
{
    return std::forward< type >(r.value);
}

template< typename F, typename ...types, std::size_t ...indices >
decltype(auto) apply_inverse(F & f, types &... values, std::index_sequence< indices... >)
{
    struct : ref< indices, types >... {} refs{{values}...};
    constexpr std::size_t top = sizeof...(indices) - 1;
    return std::forward< F >(f)(get< top - indices >(refs)...);
}

template< typename F, typename ...types >
decltype(auto) apply_inverse(F && f, types &&... values)
{
    return apply_inverse< F, types... >(f, values..., std::index_sequence_for< types... >{});
}

#include <iostream>

int main()
{
    auto const print = [] (auto const &... value) -> std::ostream & { return (std::cout << ... << value); };
    apply_inverse(print, 1, 2, 3) << std::endl;
}

Live example.

It just tries to revert the arguments passed and applies some function to them.

For G++ it compiles fine, but for clang++ (even from trunk) it gives the following error:

error: no matching function for call to 'apply_inverse'

I think the reason is the fact, that in upper overloading there is a parameter after parameter pack in the function prototype. But types for all the arguments in arguments pack are explicitly specified.

Is it right for compiler to accept the code?

Georgiageorgian answered 21/12, 2016 at 12:16 Comment(4)
MCVEErving
Reduced further: coliru.stacked-crooked.com/a/82f3d4b32bcffe56Contradict
@Contradict Isn't clang right in this case, because of how parameters packs work?Sorbian
I don't think it's specified, but the g++ approach to let all explicitly specified type arguments be consumed by the first (non-deduced here) parameter pack from a parameter declaration list doesn't sound reasonable. On the other hand, a non-deduced parameter can be provided explicitly, so... ¯\_(ツ)_/¯Erving
S
0

It was not specified exactly what version of Clang refused the code above.

But at this moment Clang 12 accepts it, as well as GCC and MSVC: https://gcc.godbolt.org/z/qMc9fKTEf

So the code is perfectly legal.

Springhouse answered 12/7, 2021 at 20:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.