【问题标题】:Workaround for the lack of support for type alias specialization in C++在 C++ 中缺少对类型别名专业化的支持的解决方法
【发布时间】:2023-03-19 13:22:01
【问题描述】:
我希望能够使用文字作为 id 来引用不同的类型。
template<auto>
using type = void;
template<>
using type<0> = int;
template<>
using type<1> = char;
template<>
using type<2> = string;
int main()
{
type<0> var0;
type<1> var1;
type<2> var2;
}
这会导致编译器给我错误,因为 C++ 尚不支持类型别名专门化。 (实现这种功能所需的技术根本不存在)
【问题讨论】:
标签:
c++
template-specialization
type-alias
【解决方案1】:
这样就可以了,并且会给你你需要的语法。请注意,我明确使用 std::size_t 来避免专门化其他类型而不是数字。
#include <string>
#include <type_traits>
//-------------------------------------------------------------------
// hide all the boiler plate in a namespace
// use structs for partial specializations
namespace details
{
template<std::size_t N>
struct type_s { using type = void; };
template<> struct type_s<0> { using type = int; };
template<> struct type_s<1> { using type = char; };
template<> struct type_s<2> { using type = std::string; };
}
//-------------------------------------------------------------------
// now you can use a full template for alias
template<std::size_t N>
using type_t = typename details::type_s<N>::type;
//-------------------------------------------------------------------
int main()
{
type_t<0> var0{ 42 };
type_t<1> var1{ 'A' };
type_t<2> var2{ "Hello World!" };
static_assert(std::is_same_v<type_t<0>, int>);
static_assert(std::is_same_v<type_t<1>, char>);
static_assert(std::is_same_v<type_t<2>, std::string>);
static_assert(std::is_same_v<decltype(var0), int>);
static_assert(std::is_same_v<decltype(var1), char>);
static_assert(std::is_same_v<decltype(var2), std::string>);
}
【解决方案2】:
别名模板中不允许部分特化,但是,您可以改用std::conditional:
#include <type_traits>
#include <string>
// ...
template <auto X>
using type = std::conditional_t<X == 0, int,
std::conditional_t<X == 1, char,
std::conditional_t<X == 2, std::string,
void>>>;
【解决方案3】:
幸运的是,我找到了一种解决方法,它使用了 C++ 支持的类专业化:
template<auto>
struct TypeAliasWrapper;
template<>
struct TypeAliasWrapper<0>{using type = int;};
template<>
struct TypeAliasWrapper<1>{using type = char;};
template<>
struct TypeAliasWrapper<2>{using type = string;};
int main()
{
TypeAliasWrapper<0>::type var0;
TypeAliasWrapper<1>::type var1;
TypeAliasWrapper<2>::type var2;
}