构建一个' is_template_instantiable'在C ++中输入trait

时间:2018-06-02 15:58:32

标签: c++ templates variadic-templates c++17 typetraits

是否可以在C ++中构造一个类型特征,用于检查给定模板类型是否可以使用给定类型作为模板参数进行实例化?如果有可能,怎么办呢?

例如:

static_assert(is_template_instantiable_v<std::optional, int, int>);
static_assert(is_template_instantiable_v<std::vector, double>);

第一个断言会失败,因为std::optional只需要一个模板参数。第二个断言不会失败,std::vector可能只用一个模板参数进行实例化,因为它的第二个模板参数有一个默认值。

如果可能的话,在下列情况下是否可以让类型特征为假(并且不会触发编译错误):

static_assert(is_template_instantiable_v<std::vector, int &>);

因为std::vector可能无法使用引用作为其值类型进行实例化。

我的猜测是第一个可能复制的例子,而第二个例子不能仅使用标准C ++代码完成。

1 个答案:

答案 0 :(得分:4)

我认为第一个要求适用于基于detection idiom的方法:

namespace detail
{
    template<template<typename...> typename T, typename AlwaysVoid, typename... Ts>
    struct is_template_instantiable :
        std::false_type {};

    template<template<typename...> typename T, typename... Ts>
    struct is_template_instantiable<T, std::void_t<T<Ts...>>, Ts...> :
        std::true_type {};

    template<template<typename...> typename T, typename... Ts>
    inline constexpr auto is_template_instantiable_v =
        is_template_instantiable<T, void, Ts...>::value;
}

然后,用:

template<typename T = void>
struct X{};

它产生:

static_assert(detail::is_template_instantiable_v<X>);
static_assert(detail::is_template_instantiable_v<X, void>);
static_assert(!detail::is_template_instantiable_v<X, void, int>);

EXAMPLE

然而,对于这种类型的特质,我无法解决第二个挑战......