无法使用auto to parametrize true_type检测T :: value()

Tay*_*ols 7 c++ sfinae language-lawyer template-meta-programming c++17

使用SFINAE,has_value_int<T>并且has_value_auto<T>都试图检测类是否T有一个static constexpr命名的功能value.

  • 使用int以参数化true_type,has_value_int<T>适用于演示类passfail.
  • 使用auto参数化true_type,has_value_auto<T>始终返回false.

使用int和使用之间有什么区别auto,为什么不起作用auto

具体来说,为什么重载喜欢match_auto(...)match_auto(int)

#include <iostream>

using namespace std;

// parametrize true_type 
template <int> using true_int = true_type; // works
template <auto> using true_auto = true_type; // does not work

// detect if T::value() is a valid compile-time expression
template <class T> true_int<(T::value(), void(), 0)> match_int(int);
template <class T> true_auto<(T::value(), void(), 0)> match_auto(int);
template <class> false_type match_int(...); // sometimes called
template <class> false_type match_auto(...); // always called
template <class T>
static constexpr bool has_value_int = decltype(match_int<T>(0))::value;
template <class T>
static constexpr bool has_value_auto = decltype(match_auto<T>(0))::value;

template <class T>
void demo() {
    cout << has_value_int<T> << "(int), " // sometimes false
            << has_value_auto<T> << "(auto)" << endl; // always false
}

int main() {
    struct pass { static constexpr int value() { return 1; } };
    using fail = float;

    cout << "has_value<pass> = "; demo<pass>(); // 1(int), 0(auto)
    cout << "has_value<fail> = "; demo<fail>(); // 0(int), 0(auto)

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:使用gcc 7.3.0编译.与clang作品相同.

Rak*_*111 2

没有区别; 这是一个 gcc 错误,由 Barry 报告为#86703

作为解决方法,不要使用函数:

// detect if T::value() is a valid compile-time expression
template <typename T, typename = void> struct match_auto : std::false_type {};

template <typename T>
struct match_auto<T, std::void_t<true_auto<(T::value(), void(), 0)>>>
    : std::true_type {};

template <class T> static constexpr bool has_value_auto = match_auto<T>::value;
Run Code Online (Sandbox Code Playgroud)