键入别名模板参数包
在下面的示例中,我试图基本上别名模板参数包。键入别名模板参数包
这在标准中是不可能的,所以我发现人们用元组或空的模板结构来解决限制。但是我的情况似乎有所不同,因为我没有一个参数参数类型包匹配 ...
(我知道这个样品看起来很蠢,但它是一个最小的PoC,在代码库类型串变长了不少这真的很有用。)
#include <iostream> #include <tuple>
template<typename T>
void f(T t)
{
std::cout << "templated f()" << std::endl;
}
template<>
void f(int t)
{
std::cout << "specialized f()" << std::endl;
}
template<typename A, typename B>
void fn()
{
f(A());
}
template<int, char>
void fn()
{
int a;
f(a);
}
// Can't seem to define this correctly.
//using MyType = std::tuple<int, char>()::type;
int
main(int, char**)
{
fn<char, char>();
// I have
fn<int, char>();
// I want some alias;
//fn<MyType>();
return 0;
}
参考文献;
- Is it possible to typedef a parameter pack?
- Using template parameter pack instead of macro
- Aliasing a template parameter pack
回答:
如果我们用一个模板空结构别名类型包,它可以使用您的原始功能SFINAE这样,当它被调用为我们的特殊结构简单地转发封装类型包装到原始实施。
这里是如何会看在C++ 14:
template <typename... Types> struct TypePack {};
// Helper meta functions to determine
// if the template param is a TypePack struct.
template <typename... Ts>
static constexpr bool is_typepack_v = false;
template <typename... Ts>
static constexpr bool is_typepack_v<TypePack<Ts...>> = true;
template <typename... Ts>
// Enabled whenever template parameter is not a TypePack.
typename std::enable_if<not is_typepack_v<Ts...>>::type
fn() { // FN_A
std::cout << "Generic\n";
}
template <>
// Complete specialization, selected over generic fn for <char,int>
void fn<char,int>() { // FN_B
std::cout << "Specialized for char,int\n";
}
template <typename T>
// Enabled when template param is a TypePack.
typename std::enable_if<is_typepack_v<T>>::type
fn() { // FN_C
forward_fn(T{});
}
// forward_fn() extracts the types from a TypePack argument
// and invokes fn with it.
template <typename ...T>
void forward_fn(TypePack<T...> /*unused*/) {
std::cout << "Forwarding a pack alias\n";
fn<T...>();
}
// To alias a type pack use TypePack<T1,T2..,Tn>
using CharIntPack = TypePack<char,int>;
int main() {
fn<char,char>(); // invokes FN_A
fn<char,int>(); // invokes FN_B
fn<CharIntPack>(); // invokes FN_C which then invokes FN_B
return 0;
}
这将产生以下的输出:
Generic Specialized for char,int
Forwarding a pack alias
Specialized for char,int
我喜欢这种方法,这种“招“在定义功能时只需要一次,用户完全可以不知道它。
回答:
的参数组必须是公正的,几种类型的列表。可以通过使用...操作符来转发参数包(一旦有参数包),从而将参数包重新扩展为列表,但必须具有这些类型。使用MyType = std :: tuple():: type;注意: 不会工作,因为元组没有'type'成员。你甚至不能这样做(有或没有......): template struct holder { typedef Types ... type; }; using my_type = holder :: type;
回答:
在下面的示例中,我试图给别名模板参数包 基本上。
这在标准中是不可能的,所以我发现人们用 限制了一个元组或空的模板结构。
std::tuple<...>
做混叠参数包是伟大的!
然而,我的情况似乎不同,因为我没有参数 参数类型包匹配...
那么,这些在那里你会发现,类模板实际上比函数模板更强大的一个案例 - 在这种情况下,我们可以有部分模板特;所以,如果你决定使用一个类模板与超载operator()
,我也确实讲过,它可能:
Demo:
template<typename... A> struct fn
{
void operator()() const
{ std::cout << "primary f()" << std::endl; }
};
template<typename... A>
struct fn<std::tuple<A...>>
{
void operator()() const
{ std::cout << "specialized on unlimited params()" << std::endl; }
};
template<>
struct fn<std::tuple<char, double*>>
{
void operator()() const
{ std::cout << "specialized on f<char, double*>()" << std::endl; }
};
template<typename A, typename B>
struct fn<std::tuple<A, B>>
{
void operator()() const
{ std::cout << "specialized on two params f()" << std::endl; }
};
// Can't seem to define this correctly.
using MyType = std::tuple<int, char>;
using MyType2 = std::tuple<char, double*>;
using MyType3 = std::tuple<int, char, double, void*>;
int main()
{
fn<int, char>()();
fn<MyType>()();
fn<MyType2>()();
fn<MyType3>()();
return 0;
}
输出:
primary f() specialized on two params f()
specialized on f<char, double*>()
specialized on unlimited params()
回答:
由于C++ 14,如果你不想重载或重写你的函数,也不想编写一个仿函数类模板,你可以使用一个通用的lambda来在本地将一个类型列表变成一个参数包:
template<typename T> struct quote{ using type = T; };
template<typename T>
using unpack = typename T::type;
template<typename... T>
using params = std::tuple<quote<T>...>;
// to be used as
template<typename A, typename B>
void foo();
using my_params = params<int,char>;
int main()
{
std::apply([](auto... params){ foo< unpack<decltype(params)>... >(); }, my_params{});
}
PS:std::apply
需要C++ 17,而是可以以> = C++ 11以及被实现...
PPS:在C++ 20,我们甚至可以写[]<typename... T>(){ foo<T...>(); }
使该解决方案更清洁......
以上是 键入别名模板参数包 的全部内容, 来源链接: utcz.com/qa/266302.html