编写自定义 c++14 风格的类型别名

Writing custom c++14-style type aliases

我想为 std::is_base_of 创建一个 _t 别名,类似于 std::enable_if_tstd::enable_if 的别名。所以我将以下内容添加到我的标准 header:

namespace std {
  template<typename T, typename U>
  using is_base_of_t = typename is_base_of<T,U>::type;
}

我在以下上下文中使用这个新别名:

template <typename SpaceT,
          typename TagT,
          typename = std::enable_if_t<std::is_base_of_t<Space,SpaceT>>>
class SpatialTree : public SpaceT {
};

我收到以下 gcc 错误:

SpatialTree.h:48:101: error: type/value mismatch at argument 1 in template parameter list for ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type’
 template <typename SpaceT, typename TagT, typename = std::enable_if_t<std::is_base_of_t<Space,SpaceT>>>

我做错了什么?

std::enable_if 定义如下:

template< bool B, class T = void >
struct enable_if;

第一个参数是 ,不是类型。您需要传入 std::is_base_of<Space,SpaceT>::value 作为第一个参数。对于 C++14,正确的别名应该是 variable template:

template <class Base, class Derived>
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>::value;

你会以同样的方式使用:

template <typename SpaceT, typename TagT,
          typename = std::enable_if_t<is_base_of_v<Space,SpaceT>>>
                                                ^^^
class SpatialTree : public SpaceT {
};

后者目前存在于<experimental/type_traits>

enable_if[_t] 想要一个 bool 作为它的第一个参数。您必须编写 std::enable_if_t<std::is_base_of_t<Space,SpaceT>::value>std::enable_if_t<std::is_base_of_t<Space,SpaceT>{}>,否则您将传递一个需要 bool 的类型。

但是,您可能想要定义 std::experimental::is_base_of_v 的对应物:

template <class Base, class Derived>
constexpr bool is_base_of_v = std::is_base_of<Base, Derived>{};

并用作 std::enable_if_t<is_base_of_v<Space, SpaceT>>.

也就是说,我不会在命名空间 std 中定义这些模板中的任何一个,因为这会根据 [namespace.std]/1.

调用 UB

从 Clang 3.6 和 g++ 5.1 开始可用

#include <experimental/type_traits>

using namespace std::experimental;

struct B {}; struct D : B {};

int main() 
{
    static_assert(is_base_of_v<B, D>, "");
}