指向成员的指针:在GCC中工作,但在VS2015中不工作
Pointer to member: works in GCC but not in VS2015
我正在尝试实现一个"属性"系统,将c++实例转换为JSON,反之亦然。我从Guillaume Racicot对这个问题的回答中提取了一部分代码(c++ JSON序列化)并简化了它。
我是这样做的。我有一个Property
类:
template <typename Class, typename T>
struct Property {
constexpr Property(T Class::* member, const char* name) : m_member(member), m_name(name) {}
T Class::* m_member;
const char* m_name;
};
m_member指向Class
的一个特定成员
假设我想为User
类定义属性,我希望能够像这样进行,能够为成员分配一个属性名称:
class User
{
public:
int age;
constexpr static auto properties = std::make_tuple(
Property<User, int>(&User::age, "age")
);
}
此代码在GCC(http://coliru.stacked-crooked.com/a/276ac099068579fd)中编译和工作正确,但在Visual Studio 2015 Update 3中不正确。我得到这些错误:
main.cpp(19) : error C2327 : 'User::age' : is not a type name, static, or enumerator
main.cpp(19) : error C2065 : 'age' : undeclared identifier
main.cpp(20) : error C2672 : 'std::make_tuple' : no matching overloaded function found
main.cpp(20) : error C2119 : 'properties' : the type for 'auto' cannot be deduced from an empty initializer
是否有一个解决方案,使其在Visual Studio 2015 Update 3中工作?
我的首选解决方案是将properties
成员数据替换为properties
成员函数:
class User
{
public:
int age;
constexpr static auto properties() { return std::make_tuple(
Property<User, int>(&User::age, "age")
); }
};
之所以有效,是因为在成员函数的定义中,类被认为是完全定义的。它还具有理想的属性,即如果使用odr,则不需要单独定义properties
。
当MSVC想要计算properties
的类型时,它不知道User
有一个成员age
。
我们可以解决这个问题。
template<class T>struct tag_t{constexpr tag_t(){};};
template<class T>constexpr tag_t<T> tag{};
template<class T>
using properties = decltype( get_properties( tag<T> ) );
class User
{
public:
int age;
};
constexpr auto get_properties(tag_t<User>) {
return std::make_tuple(
Property<User, int>(&User::age, "age")
);
}
在JSON反射代码中,只需将std::decay_t<T>::properties
替换为get_properties( tag<std::decay_t<T>> )
。
这有几个优点。首先,可以对一些不属于自己或希望无缝地使用属性修改的类进行改造。通过仔细使用名称空间和ADL启用调用点,您甚至可以对std
中的(某些)类型这样做(仅具有public成员;至少配对)。
第二,它避免了属性上可能的odr使用需求。属性现在是一个constexpr
返回值,而不是一些可能需要存储的全局数据。
friend
内联编写属性,以获得最大的灵活性。
如果绝对需要在User类中定义属性,也许您可以使用helper模板化的constexpr函数,如:
#include <tuple>
template <typename Class, typename T>
struct Property {
constexpr Property(T Class::* const member) : m_member{ member } {}
T Class::* const m_member;
};
template <class T, class V>
constexpr Property<T, V> get_age_property() {
return Property<T, V>(&T::age);
}
class User
{
public:
int age;
constexpr static std::tuple<Property<User, int>> properties = std::make_tuple(
get_age_property<User, int>()
);
};
int main()
{
}
它似乎可以在webcompiler中编译,即vc++ 19.00.23720.0
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- 编译在我的 Mac 上工作,但在集群 (Linux) 上不起作用
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- C++代码在台式机上工作正常,但在笔记本电脑上则不行
- 实现 DFS 在较短的输入下工作正常,但在较大的输入下会抛出分段错误
- 代码在Visual Studio 2017中不起作用,但在VS代码中工作
- 请发现它在 dev 中工作的错误,但在 hackerrank 中不起作用
- OpenCV Tracker 属性访问在 ARM 上因 SEGFAULT 而失败,但在 X86_64 中工作
- 自定义内存管理器在发布模式下工作正常,但在调试模式下则不然
- SIGABRT 和线程相关的异常,但在调试期间工作正常
- ostream_iterator运算符=在pair<int,int>上失败,但在包装器类上工作。我不能为成对<>重载运算符<<吗?
- .exe应用程序在windows10中创建新模块时抛出错误,但在windows7中工作正常
- 为什么这在 c++ 中不起作用,但在 python 中工作
- 我的代码在作为参数传入 .begin() 时不起作用,但在我将 .begin() 转换为迭代器后工作
- PlayFunction在DLL中不起作用,但在独立的exe中工作
- mkdir 从命令行工作,但在使用 NFS 时C++失败
- Makefile在Linux中工作,但在Windows下不起作用,在子目录中找不到文件
- C++代码在 Linux 上按预期工作,但在 Windows 上则不然
- 设备与Visa在Python中工作的通信,但在C 中不进行
- 错误:从初始值设定项列表向数组赋值;在ubuntu 1004上工作但在14.04上不工作的代码