使用void_t的成员检测 [英] Member detection using void_t

查看:89
本文介绍了使用void_t的成员检测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于C ++ 14中的成员检测,我使用了基于示例此处的代码,但是似乎没有用。

For member detection in C++14 I used code based on the example here, but it does no seem to work.

一个完整的示例:

#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; }

使用 clang ++ --std = c ++ 14 test.cpp进行编译在OS X上,编译器版本( clang ++ --version ): Apple LLVM版本7.0.2(clang-700.1)。 81)

Compiled using clang++ --std=c++14 test.cpp on OS X, compiler version (clang++ --version): Apple LLVM version 7.0.2 (clang-700.1.81)

第二个断言成功,但第一个断言成功。为什么?我也尝试使用 decltype(T :: substr)代替 typename T :: subset ,结果相同。

The second assert succeeds, but the first fails. Why? I have also tried using decltype(T::substr) instead of typename T::subset, with the same result.

推荐答案

寻找 T :: substr 并不相同寻找一个名为 substr 的成员函数。 gcc.godbolt.org示例

Looking for T::substr is not the same as looking for a member function called substr. gcc.godbolt.org example

您可以检查是否通过使用 std :: declval< T>()存在成员函数 并使用 decltype 来获得

You can check if a member function exists by using std::declval<T>() and using decltype to get the return type of the member function.

如果成员函数存在,则 decltype(...)将是一个格式正确的表达式,不会触发SFINAE-因此 static_assert 将正确运行。

If the member function exists, decltype(...) will be a well-formed expression and will not trigger SFINAE - therefore the the static_assert will work correctly.

#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; }

请注意, decltype(std :: declval< T>()。 substr(1,1))检查 T 是否具有 substr 成员,该成员可以是用参数 1、1 调用。 (例如,不能保证此 是成员函数,也可以是functor数据成员。)

Note that decltype(std::declval<T>().substr(1, 1)) checks whether T has a substr member that can be called with arguments 1, 1. (This is not guaranteed to be a member function, it could also be a functor data member, for example.)

正如AndyG在评论中所说,另一种可能的方法是使用 decltype 来验证成员的类型函数指针。

As said by AndyG in the comments, another possible approach is using decltype to "validate" the type of a member function pointer.

示例:

HasMember_substr<T, void_t< decltype(&T::substr)>

请注意,如果名称 substr 已重载,并且不保证可以与标准库中的任何类型一起使用

Note that this will not work if the name substr is overloaded, and it is not guaranteed to work with any type in the standard library.

这篇关于使用void_t的成员检测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆