SFINAE失败,出现模板非类型引用参数

时间:2019-07-13 14:05:14

标签: gcc clang c++17 sfinae non-type

考虑以下代码:

constexpr int XX = 10;

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

和:

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

在这里,我期望BBstd::true_type,但对于std::false_typegcc-8.3来说都是clang-8.0。这是这些编译器中的错误吗?

请注意,当我将BB更改为std::true_type时,auto&变成了auto。另请注意,如果我使用gcc而不是int const,则auto的情况相同,因此int const&的收益为std::false_type,而int const的收益为到std::true_type,而对于clang int const&产生std::true_type。您可以找到实时示例here

是否有一种解决方法,可以使用非类型引用模板来进行这种SFINAE?关键是要拥有IsInstantiationOfBan之类的实用工具。

1 个答案:

答案 0 :(得分:2)

您可能想要auto &而不是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]

在您遇到第一个问题时,c语可能要求const之前的auto &修饰符来实现const正确性(constexpr变量也可能是const)。 [example]