C++ 处理普通混合类型和非混合类型的可变模板
因此,我试图创建一个类型特征,它表示两个“外部”类类型是否相同 例如,C++ 处理普通混合类型和非混合类型的可变模板,c++,variadic-templates,template-meta-programming,generic-programming,typetraits,C++,Variadic Templates,Template Meta Programming,Generic Programming,Typetraits,因此,我试图创建一个类型特征,它表示两个“外部”类类型是否相同 例如,std::vector与std::vector相同,我不关心类型特征的任何内部参数 我在尝试为此创建泛型类型特征时遇到的一个问题是,我只知道如何将类型化的变量模板与非类型化的模板分开处理,这似乎阻止了我将其泛型化 是否可以处理类型化和非类型化模板参数的任何排列 下面是我实现的(包括失败的例子): //g++-std=c++17 #包括 #包括 #包括 #包括 //如果外部类型不匹配 模板 结构是外部类型相同的:std::fal
std::vector
与std::vector
相同,我不关心类型特征的任何内部参数
我在尝试为此创建泛型类型特征时遇到的一个问题是,我只知道如何将类型化的变量模板与非类型化的模板分开处理,这似乎阻止了我将其泛型化
是否可以处理类型化和非类型化模板参数的任何排列
下面是我实现的(包括失败的例子):
//g++-std=c++17
#包括
#包括
#包括
#包括
//如果外部类型不匹配
模板
结构是外部类型相同的:std::false\u类型{};
//如果比较类型的参数仅包含类型
//即std::vector
//(内部参数也是类型)
模板
结构是_outer _type _same
:std::true_type{};
//如果比较类型的参数仅包含非类型
//某个类名
模板
结构是_outer _type _same
:std::true_type{};
//如果比较类型的参数包含单个
//类型化参数后跟一些非类型化参数
//std::数组
模板
结构是_outer _type _same
:std::true_type{};
//对于参数具有模式的任何外部类型:
//单变量参数后跟一系列类型化参数:
模板
结构是_outer _type _same
:std::true_type{};
//这是为了使评估更加整洁:
模板
内联constexpr bool是\u外部\u类型\u相同\u v
=外部类型相同::值;
//无法处理的示例类型
//正确地使用上述结构模板:
模板
结构示例类型
{
A数据1;
B数据2;
常数int data3=C;
};
int main()
{
//显示其故障位置的示例:
std::cout AFAIK没有通用的解决方案。我们要么需要反射,要么需要一些新类型的模板语法,允许参数是类型参数或非类型参数。@super我不确定我会称之为稀有。std::array
是一个主要的使用案例,并且有很多类似于它的类用于矩阵和li的东西ke。@NathanOliver和std::array
样式化的东西将与这里给出的双包解决方案一起使用。混合并不少见,以非类型、类型、非类型的形式混合也很少见,其中as类型..,非类型..
相当常见。@ElliottSmith是的,这就是我说你需要添加speci的意思具体化。non-type
可以是一个包,但主要类型将需要一个专门化。type,non-type…
和type,type,non-type…
将是2个专门化。如果你添加10个,你应该有你想要的行为与一些可能丑陋的代码。可能重复
// g++ -std=c++17
#include <iostream>
#include <vector>
#include <array>
#include <type_traits>
// If the outer types don't match
template <typename, typename>
struct is_outer_type_same : std::false_type {};
// if the arguments of the compared Type contains only types
// ie. std::vector<int,std::allocator<int>>
// (the inner arguments are also types)
template <template<typename...> typename OuterType,
typename... InnerTypes1,
typename... InnerTypes2
>
struct is_outer_type_same < OuterType<InnerTypes1...>,
OuterType<InnerTypes2...>
>
: std::true_type {};
// if the arguments of the compared Type contains only non-types
// eg. SomeClassName<4,5,2>
template <template<auto...> typename OuterType,
auto... InnerVariables1,
auto... InnerVariables2
>
struct is_outer_type_same < OuterType<InnerVariables1...>,
OuterType<InnerVariables2...>
>
: std::true_type {};
// if the arguments of the compared Type contains a single
// typed-argument followed by some non-typed arguments
// ie. std::array<int, 4>
template <template<typename, auto...> typename OuterType,
typename InnerType1, auto... InnerVariables1,
typename InnerType2, auto... InnerVariables2
>
struct is_outer_type_same < OuterType<InnerType1, InnerVariables1...>,
OuterType<InnerType2, InnerVariables2...>
>
: std::true_type {};
// For any outer types whose arguments have the pattern:
// single variable argument followed by a sequence of typed arguments:
template <template<auto, typename...> typename OuterType,
auto InnerVariable1, typename... InnerTypes1,
auto InnerVariable2, typename... InnerTypes2
>
struct is_outer_type_same < OuterType<InnerVariable1, InnerTypes1...>,
OuterType<InnerVariable2, InnerTypes2...>
>
: std::true_type {};
// This is to make it neater to evaluate:
template <typename S, typename T>
inline constexpr bool is_outer_type_same_v
= is_outer_type_same<S,T>::value;
// Example type that fails to be handled
// correctly by the above struct templates:
template <typename A, typename B, int C>
struct ExampleType
{
A data1;
B data2;
const int data3 = C;
};
int main ()
{
// Examples to show where it fails:
std::cout << "Fails to find match for ExampleType: "
<< is_outer_type_same_v<ExampleType<double,int,2>,
ExampleType<double,int,2>>
<< std::endl << std::endl
// Examples to show where it works:
<< "Finds correctly: " << std::endl
<< std::endl << "Matches for std::vector: "
<< is_outer_type_same_v<std::vector<int>,
std::vector<double>>
<< is_outer_type_same_v<std::vector<std::vector<int>>,
std::vector<double>>
<< is_outer_type_same_v<std::vector<std::array<int,3>>,
std::vector<double>>
<< std::endl << "Mismatches for std::vector: "
<< is_outer_type_same_v<int,
std::vector<int>>
<< is_outer_type_same_v<std::array<int, 3>,
std::vector<int>>
<< is_outer_type_same_v<std::array<std::vector<int>, 3>,
std::vector<int>>
<< std::endl << "Matches for std::array: "
<< is_outer_type_same_v<std::array<int, 3>,
std::array<double, 7>>
<< is_outer_type_same_v<std::array<std::vector<int>, 7>,
std::array<double, 2>>
<< is_outer_type_same_v<std::array<std::array<int,3>, 8>,
std::array<std::vector<double>, 5>>
<< std::endl << "Mismatches for std::array: "
<< is_outer_type_same_v<int,
std::array<int,2>>
<< is_outer_type_same_v<std::vector<int>,
std::array<int,8>>
<< is_outer_type_same_v<std::vector<std::array<int,3>>,
std::array<int,2>>
<< std::endl;
return 0;
}