我有一个简单的特征struct hasMemberSerialize
,我试图用它来确定任何给定的类是否与callSerialize()
兼容。 struct
看起来像这样:
template<typename Type, typename ArchiveType>
struct hasMemberSerialize {
template<typename T, typename A>
static auto test(int) -> decltype(Serialization::access::callSerialize(std::declval<A&>(), std::declval<T&>()), std::true_type);
template<typename, typename>
static std::false_type test(...);
static const bool value = std::is_same<decltype(test<Type, ArchiveType>(0)), std::true_type>::value;
};
这可以编译并正常运行,但是我的hasMemberSerialize::value
总是 std::false_type
。我使用了类似的方法来检查非模板方法。但是,我正在检查的callSerialize()
方法类似于:
template<typename Archive, typename Type>
static auto callSerialize(Archive& a, Type& t) -> decltype(t.serialize(a)) {
// Implementation
}
我使用std::cout
做了一些测试,如下所示:
Serialization::access::callSerialize(JSON, myType);
std::cout << std::boolalpha
<< hasMemberSerialize<MyType, JSONOutputArchive>::value << std::endl;
方法调用callSerialize(JSON, myType)
可以正常工作并序列化类型;但是,hasMemberSerialize::value
打印false
。最后,myType
是一个简单的测试类:
class MyType {
int myInt;
public:
MyType() : myInt(4) {}
template<typename Archive>
void serialize(Archive& a) {
a(myInt);
}
};
...
MyType myType;
答案 0 :(得分:1)
我犯了一个非常简单的错误,一行
static auto test(int) -> decltype(Serialization::access::callSerialize(std::declval<A&>(), std::declval<T&>()), std::true_type);
需要成为
static auto test(int) -> decltype(Serialization::access::callSerialize(std::declval<A&>(), std::declval<T&>()), std::true_type{});
注意:std::true_type
之后的大括号。
如Max66在其评论中所述:
关键是
decltype()
返回对象的类型;因此decltype(3)
是int
;当您写decltype(std::true_type)
(即decltype(int)
)时,您会询问类型的类型;您必须询问类型为std::true_type
的对象的类型,即decltype(std::true_type{})
或(最好是恕我直言)decltype(std::declval<std::true_type>())
答案 1 :(得分:0)
您已经发现,问题在于您必须在std::true_type{}
的末尾使用带有大括号的decltype()
所以
decltype( <other elements>, std::true_type )
错误,并给出错误,其中
decltype( <other elements>, std::true_type{} )
// .......................................^^
有效。
重点是decltype()
返回给定实体(变量,常量等)或该类型的表达式的类型;因此(举例来说)给定decltype(3)
,您将得到int
。
如果你写
decltype( std::true_type )
您要求输入类型的类型,这是错误的。
如果你写
decltype( std::true_type{} )
您要求类型为std::true_type{}
的元素(std::true_type
)的类型;这是正确的,您得到std::true_type
。
我建议另一种方式:
decltype( std::declval<std::true_type>() )
其中std::declval()
是标准模板函数(仅声明,但对于decltype()
而言,它返回接收到的模板类型的元素就足够了。
因此std::declval<std::true_type>()
是std::true_type
类型的表达式,而decltype()
显然返回std::true_type
。
如果类型是默认可构造的,则可以创建该类型的实体,只需在类型名称的末尾添加几个大括号即可。但是当类型不是默认可构造的时,您就无法解决这个问题。
使用std::declval()
时,即使默认类型不可构造,您也会获得给定类型的表达式。
在std::true_type
的情况下,您可以用两种方式解决,但我建议无论如何都要使用std::declval()
。