对于C++ 14中的成员检测,我在这里使用了基于示例的代码,但它似乎没有用.
一个完整的例子:
#include <string>
template <typename...>
using void_t = void;
template <typename, typename = void> class HasMember_substr : public std::false_type {};
template <typename T> class HasMember_substr<T, void_t<typename T::substr>> : public std::true_type {};
template <typename, typename = void> class HasMember_fff : public std::false_type {};
template <typename T> class HasMember_fff<T, void_t<typename T::fff>> : public std::true_type {};
static_assert(HasMember_substr<std::string>::value, "");
static_assert(!HasMember_fff<std::string>::value, "");
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
使用编译clang++ --std=c++14 test.cpp在OS X上,编译器版本(clang++ --version):Apple LLVM version 7.0.2 (clang-700.1.81)
第二个断言成功,但第一个失败.为什么?我也试过用decltype(T::substr)而不是typename T::subset,用相同的结果.
Vit*_*meo 11
寻找T::substr与查找名为的成员函数不同substr.gcc.godbolt.org的例子
您可以通过使用std::declval<T>()和使用decltype来获取成员函数的返回类型来检查成员函数是否存在.
如果成员函数存在,decltype(...)将是一个格式良好的表达式,并且不会触发SFINAE - 因此static_assert它将正常工作.
#include <string>
#include <type_traits>
#include <utility>
template <typename...>
using void_t = void;
template <typename, typename = void>
class HasMember_substr : public std::false_type {};
template <typename T>
class HasMember_substr<T, void_t<
decltype(std::declval<T>().substr(1, 1))>
> : public std::true_type {};
static_assert(HasMember_substr<std::string>::value, "");
int main() { return 0; }
Run Code Online (Sandbox Code Playgroud)
请注意,decltype(std::declval<T>().substr(1, 1))检查是否T具有substr可以使用参数调用的成员1, 1.(例如,这不能保证是成员函数,也可以是函子数据成员.)
正如AndyG在评论中所说,另一种可能的方法是使用decltype"验证"成员函数指针的类型.
例:
HasMember_substr<T, void_t< decltype(&T::substr)>
Run Code Online (Sandbox Code Playgroud)
请注意,如果名称substr过载,这将不起作用,并且不能保证它与标准库中的任何类型一起使用.