1

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.

Vahagn
  • 4,670
  • 9
  • 43
  • 72
  • I can't really see anything in the Standard that clearly states how template argument deduction works for a non-type template parameter containing a placeholder type. – aschepler Jul 14 '19 at 00:14

1 Answers1

2

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].

W.F.
  • 13,888
  • 2
  • 34
  • 81
  • 1
    This is a Clang bug I suspect, isn't it? – Johannes Schaub - litb Jul 14 '19 at 10:43
  • @JohannesSchaub-litb Indeed it wasn't explicilty staded in my answer was it :)? `auto &` should also match to `const`. Probably [this](https://stackoverflow.com/questions/7138588/c11-auto-what-if-it-gets-a-constant-reference) can do as a reference. – W.F. Jul 14 '19 at 11:09
  • thanks! I was worried that `auto` in template parameters for no reason could use different rules than `auto` elsewhere. Since this is C++, that wouldn't surprise me at all. – Johannes Schaub - litb Jul 14 '19 at 12:11