代码之家  ›  专栏  ›  技术社区  ›  Taylor Nichols

无法使用auto检测t::value()以参数化true\u类型

  •  7
  • Taylor Nichols  · 技术社区  · 7 年前

    使用SFINAE, has_value_int<T> has_value_auto<T> 两者都试图检测 T 有一个 static constexpr 名为的函数 value .

    • 使用 int 参数化 true_type , 有价值; 为…工作 演示类 pass fail .
    • 使用 auto 参数化 真实类型 , 具有“自动”值<T> 总是返回false。

    使用 内景 使用 汽车 ,为什么 汽车 不工作?

    具体来说,为什么重载解析更喜欢 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;
    }
    

    编辑: Compiled using gcc 7.3.0 . 与相同 clang works .

    1 回复  |  直到 7 年前
        1
  •  2
  •   Rakete1111    7 年前

    没有区别;这是一个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;