【问题标题】:How to check for a field existence in a type possibly using SFINAE?如何检查可能使用 SFINAE 的类型中是否存在字段?
【发布时间】:2014-08-11 10:42:03
【问题描述】:

我有一个名为 Traits 的结构,它是 T 类型的模板,Traits 有一个名为 Size 的字段。当 T 实际上有一个名为 Size 的字段时,代码编译并且一切正常。但是,当 T 是原生类型时,它显然没有 Size 字段并且代码无法编译

template <class T>
struct Traits
{
    static const size_t Size = T::Size;
};

我尝试使用 SFINAE 编写它,但它仍然无法编译

template <class T>
struct Traits
{
    static typename std::enable_if<!std::is_fundamental<T>::value, const size_t>::type Size = T::Size;
    static typename std::enable_if< std::is_fundamental<T>::value, const size_t>::type Size = sizeof(T);
};

编译错误是

error : redeclaration of `typename std::enable_if<std::is_fundamental<T>::value, const unsigned int>::type Traits<T>::Size'

这没有任何意义,因为编译器认为我在重新声明 Size 但实际上这是不可能的,因为 T 要么是基本类型,要么不是,所以我希望 Size 只声明一次。

知道出了什么问题或如何规避此问题吗? (使用 gcc 4.8.3)

【问题讨论】:

    标签: c++ linux gcc c++11


    【解决方案1】:

    SFINAE 仅在某些情况下有效,而这不是其中之一。 SFINAE 只能在类模板特化和函数模板签名的上下文中使用。将测试移动到类模板专业化中,它应该可以按预期工作:

    template <class T, class = void>
    struct Traits  //default is is fundamental
    {
        static const size_t Size = sizeof(T);
    };
    template<class T>
    struct Traits<T,std::enable_if_t<!std::is_fundamental<T>::value>>{ //if SFINAE does not remove this it is not fundamental and should have a T::Size
        static const size_t Size = T::Size;
    }
    

    使用 void_t 直接测试 T 是否有嵌套的 Size 可能会更好:

    template<typename T>
    using void_t = void;
    
    template <class T, class = void>
    struct Traits  //default 
    {
        static const size_t Size = sizeof(T);
    };
    template<class T>
    struct Traits<T,void_t<decltype(T::Size)>>{ //if SFINAE does not remove this T::Size exists
        static const size_t Size = T::Size;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多