是否有指向成员特征或类似内容的指针?

发布于 2024-08-14 11:38:29 字数 991 浏览 1 评论 0原文

基于其他我的问题

考虑下面的代码

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++ 标准。 我需要解决方法。

Based on other my question.

Consider the following code

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
};

Look, I can use value_type and size as template parameter.

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

Now I want to do the same with pointer to member:

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

But I get error.

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

How to make last line to work?
Or how to get similiary result?

Note. I know that it does not work. No links to C++ Standard is needed.
I need workaround.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

紅太極 2024-08-21 11:38:29

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

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

指向成员常量表达式的指针

这不是原始问题的答案,而是 这个错误的说法。

It shouldn't work according to C++ Standard 5.19/2:

Other expressions are considered constant-expressions only for the purpose of non-local static object initialization (3.6.2). Such constant expressions shall evaluate to one of the following:
— a null pointer value (4.10),
— a null member pointer value (4.11),
— an arithmetic constant expression,
— an address constant expression,
— a reference constant expression,
— an address constant expression for a complete object type, plus or minus an integral constant expression,
or
a pointer to member constant expression.

It is not the answer to the original question, but it is the answer to this wrong statement.

别再吹冷风 2024-08-21 11:38:29

迈克是对的,它应该编译。这是 VS 中的一个错误

Mike is right that it should compile. This is a bug in VS.

心房的律动 2024-08-21 11:38:29

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

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

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

也许您可以尝试向我们提供您正在尝试对您的特征/策略类执行的操作的更全面的了解,以查看是否可以找到合适的解决方法。

Not totally an answer but do accessing Mem directly work?

ie: B1::Mem instead of B1::mp.

I'm pretty sure the standard do not allow it since we normally typedef template name when it's a type instead of accessing it directly, but technically it could maybe allow it (not sure what would be the implication). Where your solution is probably sure not to work since it require initialisation of a static member that is done at runtime (correct me if I'm wrong), so it cannot be accessed at compile time like you want to do.

Maybe you could try giving us the bigger picture of what you're trying to do with your trait/policy class to see if a suitable workaround is possible.

倾城°AllureLove 2024-08-21 11:38:29

我惊讶地发现根本没有这样的事情。至少在预期的地方,例如:

这里什么都没有 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< /a>

基于此 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 使其更清晰。)

I was surprised to find that there is not such thing. At least in the expected places, for example:

There is nothing here http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/index.html
nor near here http://en.cppreference.com/w/cpp/types/is_member_pointer

Based on this http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html and this http://en.cppreference.com/w/cpp/types/is_member_pointer it is not hard to roll your own.

#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
}

I am not sure if the names are optimal.
Also when applied to non member pointer this will give a compiler error (this design is copied from http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html), another alternative could be to return the void type (which is obviously a failure return because void cannot be a class or a member type.)

(with some small modifications it can be used with C++98, used C++11 to make it more clear.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文