C++17 之 "void_t"

  • 使用 void_t
  • void_t 的工作原理
  • 一个有趣的例子

C++ 17 提供了 void_t, 它是一个模板别名, 定义为

template<class...>
using void_t = void;

void_t 一般用于元编程. 从定义上看, void_t 的定义平淡无奇, 但利用 SFINAE 原则在元编程中却可以发挥巨大威力.

使用 void_t

例 1: 判断某类型是否有指定内嵌类型的模板定义

// primary template handles types that have no nested ::type member:
template< class, class = std::void_t<> >
struct has_type_member : std::false_type { };

// specialization recognizes types that do have a nested ::type member:
template< class T >
struct has_type_memberstd::void_t<typename T::type>> : std::true_type { };

// 此例代码来自 http://en.cppreference.com

根据例 1, 使用例 2 的代码进行测试.

例 2: 测试

// 定义两个结构 A, B
struct A
{
    typedef int type;
};

struct B {};

//
std:: cout << std::boolalpha;

// 测试
std::cout << has_type_member::value << '\n'; // prints true
std::cout << has_type_member::value << '\n'; // prints false

void_t 的工作原理

下面例 3 用于判断某个类型中是否含有成员 member. 并且结合这个例子说明使用
void_t 的 SFINAE 替换过程.

例 3

// 基本模板
template<class, class = void >
struct has_member : std::false_type
{ };

// 模板特化
template<class T>
struct has_memberstd::void_t<decltype(T::member)>> : std::true_type
{ };

// 定义两个用于测试的结构
struct A
{
    int member;
};

class B
{
};

// 测试
static_assert(has_member::value); // (1)
static_assert(has_member::value); // (2)

下面描述 SFINAE 替换过程.

一个有趣的例子

这个例子来自 http://purecpp.org/?p=1273, 用于判断参数类型是否为智能指针.

// 基本模板
template <typename T, typename = void>
struct is_smart_pointer : std::false_type
{
};

// 特化模板: 通过判断 T::-> 存在否和 T::get() 存在否来确定 T 是否一个智能指针
template <typename T>
struct is_smart_pointerstd::void_t<decltype(std::declval().operator ->()),
                    decltype(std::declval().get())>> : std::true_type
{
};

// 若对上述判断不放心, 可以再加一个条件: reset()函数. 也可以加更多的判断条件

你可能感兴趣的:(C/CPP)