假设
template<typename... Types> void bar();
我正在尝试编写一个模板结构 GimmePack
bar< GimmePack<double,3>::type >();
与
相同bar< double,double,double >();
这可能吗?
以下是我的尝试。
#include<iostream>
template<typename,size_t,typename...> struct Packstack;
template<typename Tfloat, size_t i, typename ...Types>
requires(i>0)
struct Packstack<Tfloat,i,Types...>{
using pack = typename Packstack<Tfloat,i-1,Tfloat,Types...>::pack;
};
template<typename Tfloat, typename ...Types>
struct Packstack<Tfloat,0,Types...>{
using pack... = Types...;
};
template<typename Tfloat, size_t i>
struct GimmePack{
using pack = typename Packstack<Tfloat,i>::pack;
};
我知道我可以将 Packstack 元编程代码编织到 bar 的函数定义中。 但在我正在开发的实际源代码中,bar并不是一个简单的函数,而是一个复杂模板类的模板函数,可读性会受到影响。
我还知道,在相同类型的上下文中,信息
double,double,double
相当于信息 double,3
,因此,如果 bar 是结构体,则可以构造 bar
的模板专业化(因为函数的模板专业化无效) c++)。所以我的问题是关于语法而不是概念。
在我的实际代码中,我已经尝试重新排列模板的顺序,以便编译器可以找出它们,但我的签名是
template<typename other1, typename other2, typename ...Values> bar(Values... values1, other1 o1, Values... values2, other2 o2);
似乎只要 Values... 在签名中出现两次,编译器就会希望将其显式写入。虽然看起来向量是一个不错的选择,但每个 value1...、values2... 中的数据元素都来自不相关的上下文。
我尝试在 using 语句周围的不同位置放置三个点。
在通用 lambda 表达式上使用显式模板参数列表怎么样?
template <class...>
struct mp_list {};
template <class T, std::size_t I, class... Ts>
auto GimmePack(auto f) {
if constexpr (I == 0) {
return f(mp_list<Ts...>{});
} else {
return GimmePack<T, I - 1, T, Ts...>(f);
}
}
...
// same as bar<double, double, double>();
GimmePack<double, 3>([]<class... Ts>(mp_list<Ts...>) {
return bar<Ts...>();
});
您可以使用变量模板。
#include <tuple>
template <typename T, int N>
struct GimmePack{
//using type = ...;
}
template<typename O1, typename O2, typename... Values> void bar(Values... values1, O1 other1, Values... values2, O2 other){
//...
}
template<typename O1, typename O2, typename T>
void (*make_bar)() = nullptr;
template<typename O1, typename O2, typename... Ts>
void (*make_bar<O1, O2, std::tuple<Ts...>>)(Ts..., O1, Ts..., O2) = bar<O1, O2, Ts...>;
template <typename... Args>
void caller(Args... args){
make_bar<int, int, std::tuple<double, double>>(args...); // equivalent to bar<int, int, double, double>(args...);
make_bar<int, int, GimmePack<double, 2>::type>(args...); // same
}
这只是一个想法:
你尝试过模板特化和递归吗?
// The type is (T) and count is (N).
template<typename T, int N>
struct MyStruct {
using type = typename MyStruct<T, N - 1>::type;
};
template<typename T>
struct MyStruct<T, 0> {
using type = T;
};
现在我们使用
MyStruct
为 bar
函数生成所需的参数包:
template<typename... Types>
void bar();
using MyPack = typename MyStruct<double, 3>::type;
bar<MyPack>();