代码之家  ›  专栏  ›  技术社区  ›  skypjack

自动模板参数、数据成员和常量

  •  1
  • skypjack  · 技术社区  · 6 年前

    假设我有一个指向数据成员的指针,我想知道它是否为常量。换句话说:

    struct S {
        const int i; // this is const
        int j;
    };
    

    在C++中,我曾经做过这样的事情:

    template<typename Class, typename Type, Type Class:: *>
    struct is_const_data_member: std::false_type {};
    
    template<typename Class, typename Type, const Type Class:: *Member>
    struct is_const_data_member<Class, const Type, Member>: std::true_type {};
    
    template<typename Class, typename Type, Type Class:: *Member>
    void foo() {
        const auto bar = is_const_data_member<Class, Type, Member>::value;
        // ...
    }
    

    然而,现在有了 auto 模板参数和模板参数列表非常优雅:

    template<auto Member>
    void foo() {
        // ...
    }
    

    在本例中,我发现知道数据成员是否指向常量的唯一方法是:

    const auto bar = std::is_const_v<std::remove_reference_t<decltype(std::declval<Class>().*Member)>>;
    

    然而,看起来 丑陋的 对我来说,我觉得一定有更好的方法。
    还有其他(更短的)解决方案吗?

    2 回复  |  直到 6 年前
        1
  •  1
  •   HolyBlackCat    6 年前

    你可以改变 is_const_data_member 要对单个类型模板参数进行操作,请执行以下操作:

    template<typename MemPtr>
    struct is_const_data_member: std::false_type {};
    
    template<typename Class, typename Type>
    struct is_const_data_member<const Type Class::*>: std::true_type {};
    

    然后,从 template<typename Class, typename Type, Type Class:: *Member> void foo() 你把它当作

    is_const_data_member<Type Class::*>::value
    

    (在我看来,这更直观一些。)

    来自 template<auto Member> void foo() 你把它当作

    is_const_data_member<decltype(Member)>::value
    

    你也可以重写这个特征来操作 auto 模板参数。但是通过使用类型参数,可以避免对同一类型的不同指针进行不必要的实例化,这应该是一件好事。

        2
  •  0
  •   Michael Kenzel    6 年前

    这样怎么样:

    template <typename T>
    struct is_const_data_member : std::false_type {};
    
    template <typename C, typename T>
    struct is_const_data_member<const T C::*> : std::true_type {};
    
    template <auto T>
    constexpr bool is_const_data_member_v = is_const_data_member<decltype(T)>::value;
    

    然后,例如

    struct Test
    {
        int a;
        const int b;
    };
    
    
    bool x = is_const_data_member_v<&Test::a>;
    bool y = is_const_data_member_v<&Test::b>;
    

    working test here