键入别名模板参数包

在下面的示例中,我试图基本上别名模板参数包。键入别名模板参数包

这在标准中是不可能的,所以我发现人们用元组或空的模板结构来解决限制。但是我的情况似乎有所不同,因为我没有一个参数参数类型包匹配 ...

我知道这个样品看起来很蠢,但它是一个最小的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

回到顶部