Vahagn
Vahagn

Reputation: 4840

SFINAE fails with template non-type reference argument

Consider this code:

constexpr int XX = 10;

template < auto& II > struct Ban { };
template < auto& II >
std:: true_type test(Ban<II>*);
std::false_type test(...);

and:

using BB = decltype(test(std::declval<Ban<XX>*>()));

Here I am expecting BB to be std::true_type, but it is std::false_type for both gcc-8.3 and clang-8.0. Is this a bug in these compilers?

Note that BB becomes std::true_type when I change auto& to auto. Also note that for gcc situation is the same if I use int const instead of auto, so int const& yields to std::false_type, while int const yields to std::true_type, while for clang int const& yields to std::true_type. You can find live example here.

Is there a workaround to do this kind of SFINAE with a template of non-type reference? The point is to have a utility like IsInstantiationOfBan.

Upvotes: 1

Views: 82

Answers (1)

W.F.
W.F.

Reputation: 13988

Maybe instead of auto & you want decltype(auto):

#include <type_traits>

constexpr int XX = 10;

template <decltype(auto) II > struct Ban { };
template <decltype(auto) II >
std::true_type test(Ban<II>*);
std::false_type test(...);

int main()
{
    using BB = decltype(test(std::declval<Ban<(XX)>*>()));
                                           // ^  ^ be careful for brackets!

    static_assert(std::is_same_v<BB, std::true_type>);

    return 0;
}

[live demo]

In case of your first question, clang probably requires the const specifier before auto & to fulfil const correctness (constexpr variable is also presumably const). [example].

Upvotes: 2

Related Questions