The code below gives the following compilation error:
main.cpp:5:48: error: invalid use of non-static data member 'id'
static constexpr int Type::* mem_ptr_id = &id;
^~
main.cpp:5:34: error: default initialization of an object of const type 'int Type::*const'
static constexpr int Type::* mem_ptr_id = &id;
^
= nullptr
main.cpp:6:46: error: invalid use of non-static data member 'id'
static constexpr auto mem_ptr_id_auto = &id;
^~
main.cpp:6:27: error: declaration of variable 'mem_ptr_id_auto' with deduced type 'const auto' requires an initializer
static constexpr auto mem_ptr_id_auto = &id;
^
4 errors generated.
which is kind of expected.
#include <iostream>
struct Type {
int id;
static constexpr int Type::* mem_ptr_id = &id; // &Type::id required
static constexpr auto mem_ptr_id_auto = &id; // &Type::id required
};
int main() {
Type test;
test.*Type::mem_ptr_id = 5; // same as test.id = 5
test.*Type::mem_ptr_id_auto = 5; // same as test.id = 5
std::cout << test.id << std::endl; // expected: 5
return 0;
}
I need a way to have static pointer-to-member variable of my class/structure without explicitly naming the type (class/struct) name. Any suggestions?
Note:
In order to avoid auto
to become int&
, I did pointer-to-member wrapper:
template<typename T, class E>
struct Pointer2Member {
using var_t = T;
using entity_t = E;
using mem_ptr_t = T E::*;
T E::* data;
constexpr Pointer2Member() {}
constexpr Pointer2Member(T E::* val) : data(val) {}
constexpr operator T E::* () {
return data;
}
};
template<auto ptr>
struct Pointer2MemberOf;
template<typename T, class E, T E::* ptr>
struct Pointer2MemberOf<ptr> : Pointer2Member<T, E> {
constexpr Pointer2MemberOf() : Pointer2Member<T, E>(ptr) {}
constexpr operator Pointer2Member<T, E>() {
return *this;
}
};
struct Type {
int id;
static constexpr auto mem_ptr_id = Pointer2MemberOf<&id>(); // Pointer2MemberOf<&Type::id>() required
};
but it gives same error:
main.cpp:34:58: error: invalid use of non-static data member 'id'
static constexpr auto mem_ptr_id = Pointer2MemberOf<&id>();
^~
main.cpp:34:27: error: declaration of variable 'mem_ptr_id' with deduced type 'const auto' requires an initializer
static constexpr auto mem_ptr_id = Pointer2MemberOf<&id>();
^
main.cpp:40:17: error: no member named 'mem_ptr_id_auto' in 'Type'
test.*Type::mem_ptr_id_auto = 5; // same as test.id = 5
~~~~~~^
3 errors generated.
Note 2: Follow-up on the comment "What do you need this for":
Unfortunately, it is very complicated variadic template solution which I can't talk a lot about.
What I want to achieve is to create a template class Result<...>
which can store custom member variables of different classes.
Result<User::id, User::username, Post::id>
and Result<User, Post::id>
should both be viable syntaxes and should have Result<User, Post::id>::get<PROPERTY>
which should be able to have both Result<User, Post::id>::get<User>
and Result<User, Post::id>::get<User::id>
(yes, User
, not Post
).
Imagine Result<...>
class in a library that will be used by beginner C++ programmers so I don't want to use the &User::id
syntax as it might be too complicated to comprehend for them.
Also, the static member will be auto-generated via macros like
#define Member(TYPE, NAME) TYPE _##NAME; static constexpr auto NAME = Pointer2Member(&_##NAME)
struct User {
Member(int, id);
Member(std::string, username);
};
Result<User::id> result1;
result1.get<User::id>() = 5;
Result<User> result2;
result2.get<User::id>() = 6;
result2.get<User::username>() = "John";