是否指向成员特征或类似的东西?

时间:2009-12-16 12:20:51

标签: c++ templates pointer-to-member

基于other my question

考虑以下代码

template<typename T, int N>
struct A {
  typedef T value_type; // save T to value_type
  static const int size = N; // save N to size
};

看,我可以使用value_typesize作为模板参数。

typedef A<int, 2> A1;
typedef A<A1::value_type, A1::size + 3> A2;  // OK,  A2 is A<int,5>

现在我想用指向成员的指针做同样的事情:

struct Foo {
    int m;
    int r;
};

template<int Foo::*Mem>
struct B {
   static int Foo::* const mp;
};

template<int Foo::*Mem>
int Foo::* const B<Mem>::mp = Mem; // Save pointer to member

但我得到错误。

typedef B<&Foo::m> B1;
typedef B<B1::mp>  B2;  // DOES NOT WORK

如何让最后一行工作? 或者如何获得模拟结果?

注意。我知道它不起作用。不需要指向C ++标准的链接。 我需要解决方法。

4 个答案:

答案 0 :(得分:1)

它不应该按照C ++标准5.19 / 2运行:

  

其他表达式仅被视为常量表达式,仅用于非本地静态对象初始化(3.6.2)。这些常数表达式应评估为以下之一:
   - 空指针值(4.10),
   - 空成员指针值(4.11),
   - 算术常量表达式,
   - 地址常量表达式,
   - 参考常量表达式,
   - 完整对象类型的地址常量表达式,加上或减去整数常量表达式,
  或
   - 指向成员常量表达式的指针

这不是原始问题的答案,但它是this错误陈述的答案。

答案 1 :(得分:0)

迈克是对的,它应该编译。这是VS中的bug

答案 2 :(得分:0)

不是完全答案,但直接访问Mem工作吗?

ie:B1 :: Mem而不是B1 :: mp。

我很确定标准不允许它,因为我们通常在它是类型而不是直接访问它时键入模板名称,但从技术上讲它可能允许它(不确定是什么意思)。你的解决方案可能肯定无法工作,因为它需要初始化在运行时完成的静态成员(如果我错了就纠正我),所以在编译时无法像你想要的那样访问它。

也许您可以尝试让我们更全面地了解您要对特质/政策类进行的操作,看看是否有合适的解决方法。

答案 3 :(得分:0)

我很惊讶地发现没有这样的东西。至少在预期的地方,例如:

这里没有任何内容http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/index.html 也不在附近http://en.cppreference.com/w/cpp/types/is_member_pointer

根据此http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html和此http://en.cppreference.com/w/cpp/types/is_member_pointer,您不难自行推出。

#include<type_traits> // std::is_pointer_member

template<class MP> struct member_pointer_traits_helper;

template< class T, class U >
struct member_pointer_traits_helper<T U::*>{
    using class_type = U;
    using declaration_type = T;
};

template< class MP >
struct member_pointer_traits : 
member_pointer_traits_helper<typename std::remove_cv<MP>::type> {};

struct B{
    int b;
};

int main(){
    using std::same;

    static_assert(std::is_member_pointer<int B::*>::value == true, "");
    static_assert(is_same<member_pointer_traits<int B::*>::class_type, B>{}, "");
    static_assert(is_same<member_pointer_traits<int B::*>::declaration_type, int>{}, "");
    static_assert(is_same<member_pointer_traits<decltype(&B::b)>::declaration_type, int>{}, "");
//  static_assert(is_same<member_pointer_traits<double>::class_type, B>{}, ""); // error
}

我不确定名称是否最佳。 同样,当应用于非成员指针时,这将给出编译器错误(此设计从http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html复制),另一种替代方法可能是返回void类型(这显然是失败返回因为{{1 }}不能是类或成员类型。)

(通过一些小的修改,它可以与C ++ 98一起使用,使用C ++ 11使其更清晰。)