【问题标题】:Is it possible to detect the constness of a class' method using SFINAE?是否可以使用 SFINAE 检测类方法的常量性?
【发布时间】:2012-12-21 15:30:45
【问题描述】:

考虑这个结构:

struct foo {
  void dummy() const {}
};

是否可以使用 SFINAE 检测此方法的常量性?

例如,我想在一个可以在static_assert 中使用的特征中捕获此属性:

static_assert(is_const_method<decltype(&foo::dummy)>::value, "Not const!");

我认为std::is_conststd::remove_const 在这里可以帮助我,但它们似乎不包含constness 的这种“类型”。

谢谢,

【问题讨论】:

    标签: c++ templates boost c++11 sfinae


    【解决方案1】:

    当然,看起来像这样:

    #include <type_traits>
    
    template <class T>
    struct is_const_method
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...)>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const>
        : std::true_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) volatile>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const volatile>
        : std::true_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) &>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const &>
        : std::true_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) volatile &>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const volatile &>
        : std::true_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) &&>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const &&>
        : std::true_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) volatile &&>
        : std::false_type
    {
    };
    
    template <class R, class C, class ...T>
    struct is_const_method<R (C::*)(T...) const volatile &&>
        : std::true_type
    {
    };
    
    struct foo {
      void dummy() const {}
    };
    
    int main()
    {
        static_assert(is_const_method<decltype(&foo::dummy)>::value, "Not const!");
    }
    

    【讨论】:

    • 如果您默认派生自false_type,为什么非const 的所有特化?
    • 因为我没有 R. Martinho Fernandes 聪明。 :-) 我是从我已经编写的其他代码位中复制/粘贴的,我需要列举所有不同的可能性。它看起来很乏味,直到你记得在没有可变参数的情况下尝试这样做是什么感觉! :-)
    • 请在下次会议中为模板中的 ref_qualifiercv_qualifier 占位符争论。 ;)
    • 我不知道为什么我没有先想到这个……我一定是在寻找太复杂的东西!谢谢!
    • @David ::value 来自std::true_typestd::false_type;见:en.cppreference.com/w/cpp/types/integral_constant
    【解决方案2】:

    你可以只使用部分特化。

    // false by default
    template <typename Fun>
    struct is_const_function : std::false_type {};
    
    // breakdown member function type
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const> : std::true_type {};
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const volatile> : std::true_type {};
    // consider ref-qualified ones for compilers that support it
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const&> : std::true_type {};
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const&&> : std::true_type {};
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const volatile&> : std::true_type {};
    template <typename Class, typename Result, typename... Args>
    struct is_const_function<Result (Class::*)(Args...) const volatile&&> : std::true_type {};
    

    您还可以添加更多的特化来满足 C 风格的可变参数函数,但坦率地说,亲爱的,我不在乎。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-11
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多