类型检查 constexpr 函数用于检查 C++17 上的非模板类型或模板类型

Tak*_*ndo 5 c++ type-traits c++17

我编写了类型检查 constexpr 函数。如果类型为type1ortype2则返回 true,否则返回 false。

这是代码。它按我的预期工作。

#include <type_traits>

struct type1{};
struct type2{};
struct type3{};

template <typename T>
constexpr bool is_type1or2() {
    return std::is_same_v<T, type1> || std::is_same_v<T, type2>;
}

static_assert(is_type1or2<type1>());
static_assert(is_type1or2<type2>());
static_assert(!is_type1or2<type3>());

int main(){}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/dncKo1Pbb

现在,type1更改为具有非类型参数的模板。如何进行同类型检查?

#include <type_traits>

template <std::size_t N>
struct type1{};
struct type2{};
struct type3{};

template <typename T>
constexpr bool is_type1or2() {
    return std::is_same_v<T, type2>;
}

template <typename T, std::size_t N>
constexpr bool is_type1or2() {
    return std::is_same_v<T, type1<N>>;
}

// I want to write as follows but I couldn't find a way, so far.
// static_assert(is_type1or2<type1<42>>());
// so I pass explicit second template argument 42.
static_assert(is_type1or2<type1<42>, 42>());

static_assert(is_type1or2<type2>());
static_assert(!is_type1or2<type3>());

int main(){}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/G1o5447z8

我尝试过,但无法消除第二个模板参数。它避免了通用代码。有什么好的方法来检查类型是type1<anyN>ortype2吗?

在我的实际情况中,我有 20 个非模板类型(如 )type2和 20 个模板类型(如type1. 其中一半需要匹配。我想尽可能避免代码重复。

明确要求

对于模板类型type1<N>N并不重要。这两个模板都很type1重要。is_type1or2<type1<10>>()所以和的结果is_type1or2<type1<20>>()总是相同的。我不需要定义基于单独模板参数专业化的匹配。

cig*_*ien 1

如果您更改 的语法static_assert以接受类型作为函数参数,则可以轻松解决此问题,因为这将允许函数模板参数推导(请参阅Takatoshi Kondo回答)。

然而,这也可以通过编写一个模板来检查类型是否是模板的实例化来解决:

template<template <std::size_t> typename, typename>
struct is_instance_of : std::false_type {};

template<template <std::size_t> typename T, std::size_t N>
struct is_instance_of<T, T<N>> : std::true_type {}; 
Run Code Online (Sandbox Code Playgroud)

现在is_instance_of可以在函数中使用(不带参数推导):

template <typename T>
constexpr bool is_type1or2() {
    return 
        is_instance_of<type1, T>::value  // repeat for other templates that take a size_t parameter 
        or std::is_same_v<T, type2>;     // repeat for non-template types
}
Run Code Online (Sandbox Code Playgroud)

如果您希望允许使用其他模板类型(即采用除 a 之外的参数的模板size_t),您可以is_instance_of根据需要进行编辑。

这是一个演示