5

基于其他我的问题

考虑以下代码

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_typeandsize作为模板参数。

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

4 回答 4

1

它不应该根据 C++ 标准 5.19/2 工作:

仅出于非局部静态对象初始化(3.6.2)的目的,其他表达式被视为常量表达式。此类常量表达式的计算结果应为以下之一:
— 一个空指针值 (4.10),
— 一个空成员指针值 (4.11),
— 一个算术常量表达式,
— 一个地址常量表达式,
— 一个引用常量表达式,
— 一个完整对象类型的地址常量表达式,加上或减去一个整数常量表达式,
或者
- 指向成员常量表达式的指针

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

于 2009-12-16T18:30:11.663 回答
0

Mike 是正确的,它应该编译。这是VS中的一个错误。

于 2009-12-16T17:21:40.433 回答
0

不完全是答案,但直接访问 Mem 有效吗?

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

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

也许您可以尝试让我们更全面地了解您正在尝试对您的 trait/policy 类做什么,看看是否有合适的解决方法。

于 2009-12-17T14:56:39.583 回答
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类型(这显然是失败返回,因为void不能是类或成员类型。)

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

于 2016-05-10T11:41:08.290 回答