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?

Tomilov Anatoliy
  • 15,657
  • 10
  • 64
  • 169
  • [MCVE](http://coliru.stacked-crooked.com/a/7ff90251ab8e0bd3) – Piotr Skotnicki Dec 21 '16 at 12:45
  • Reduced further: http://coliru.stacked-crooked.com/a/82f3d4b32bcffe56 – T.C. Dec 21 '16 at 13:58
  • @T.C. Isn't clang right in this case, because of how parameters packs work? – skypjack Dec 21 '16 at 14:24
  • 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... ¯\\_(ツ)_/¯ – Piotr Skotnicki Dec 21 '16 at 14:58

1 Answers1

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.

Fedor
  • 17,146
  • 13
  • 40
  • 131