C++ 检测特定的C++;类型有一个成员,继承的成员除外
我想检测特定类型是否有成员:直接而不是继承的结果C++ 检测特定的C++;类型有一个成员,继承的成员除外,c++,inheritance,c++14,detection,typetraits,C++,Inheritance,C++14,Detection,Typetraits,我想检测特定类型是否有成员:直接而不是继承的结果 #include <type_traits> #include <iostream> struct A { // would match std::declval<B*> as B* -> A*, // hence forcing failure through B** -> A**. // void member(A*) { } void member(A**)
#include <type_traits>
#include <iostream>
struct A {
// would match std::declval<B*> as B* -> A*,
// hence forcing failure through B** -> A**.
// void member(A*) { }
void member(A**) { }
};
struct B : A {
// succeeds compilation aka "found" if not commented
// void member(B**) { }
};
int main()
{
// This actually fails to compile, which is OKAY because it
// WORKS when used with SFINAE during the actual detection.
// This is just a simple example to run.
// error: invalid conversion from 'B**' to 'A**'
std::cout << "B has member? "
<< std::is_member_function_pointer<
decltype(std::declval<B>().member(std::declval<B**>()))
>::value
<< std::endl;
}
目的是确定特定类型是否具有诸如序列化能力之类的特性。当然,为了扩展示例,即使父类型具有序列化功能,子类型也可能没有序列化功能
- 是否有(如果有)针对该请求的“标准”解决方案
- 底部显示的不可转换指针方法是否存在缺陷(不包括其施加的限制)
is\u member\u function\u pointer
或其他检测机制时,继承起作用。请注意,即使B没有定义成员,输出也是“1”
#include <type_traits>
#include <iostream>
struct A {
void member() { }
};
struct B : A {
};
int main()
{
std::cout << "B has member? "
<< std::is_member_function_pointer<decltype(&B::member)>::value
<< std::endl;
}
这可能适合您:
#包括
#包括
结构A{
无效成员(A**)
{}
};
结构B:A
{};
模板
结构hasMember:std::false_type{};
模板
结构hasMember>
:std::is_samemember()),void>
{};
int main(){
std::cout有一个巧妙的技巧可以帮助解决这个问题
&B::member
的类型实际上是void(A::*)()
,而不是void(B::*)()
(如果继承了member
)
使用SFINAE检查&B::member
是否存在并具有正确的类型:
template <typename T, typename = void>
struct has_member : std::false_type {};
template <typename T> struct has_member
<T, std::enable_if_t<std::is_same_v<void (T::*)(), decltype(&T::member)>>>
: std::true_type
{};
使用&B::member
是void(A::*)()
这一事实,您可以这样做
template <typename C, typename Sig>
struct classMember : std::false_type{};
template <typename C, typename Ret, typename ... Ts>
struct classMember<C, Ret (C::*)(Ts...)> : std::true_type{};
// and other specialization for cv and ref and c ellipsis
template <typename, typename = void>
struct hasMember : std::false_type {};
template <typename T>
struct hasMember<T, std::enable_if_t<classMember<T, decltype(&T::member)>::value>> : std::true_type
{};
模板
结构类成员:std::false_type{};
模板
结构类成员:std::true_type{};
//以及cv、ref和c省略号的其他专门化
模板
结构hasMember:std::false_type{};
模板
结构hasMember:std::true\u类型
{};
这是否回答了您的问题?您可以要求传递给函数的内容专门化您为库创建的某些类型特征,而不是试图检测成员的存在,然后您可以检查类型特征的结果。@胡桃夹子不,它不会-除非隐藏了详细信息。该答案/问题不处理继承,这就是这个问题产生的原因。@NathanOliver对于“不引人注目的形式”也做了同样的事情:)我希望对于“突兀的/内联的”形式也能得到类似的效果。@BasileStrynkevitch所以现在我只需要为Clang、GCC、IIC、NVCC等编写、安装和维护插件;-)[Pro-Tip]((T*)nullptr)
可以替换为std::declval()
谢谢。原始代码中的代码就是这样被有效地使用的(例如,SFINAE/检测器被删除)。但是,它仍然依赖于不可转换的指针/非重写方法来运行。它在这里是可行的。只希望可以在不需要此类方法的情况下进行推断。它实际上不起作用。请检查example@NutCracker那是因为它需要一个不同的成员签名
:@HolyBlackCat哇,那..行了!我无法想象昨天我们知道了如何在中工作是一样的。注意到“类型的&B::成员实际上是无效的(A::*)()”,这也是非常简单的。一些小垫片和工作在clang3.9.1中(是的,旧的,它是我们的一个..基线..目标)。
template <typename C, typename Sig>
struct classMember : std::false_type{};
template <typename C, typename Ret, typename ... Ts>
struct classMember<C, Ret (C::*)(Ts...)> : std::true_type{};
// and other specialization for cv and ref and c ellipsis
template <typename, typename = void>
struct hasMember : std::false_type {};
template <typename T>
struct hasMember<T, std::enable_if_t<classMember<T, decltype(&T::member)>::value>> : std::true_type
{};