没有元组的 Variadics 模板
Variadics template without tuple
我正在从事一个非常特殊的项目,因为我无法使用所有 C++11 功能。特别是,我有 variadics
模板但没有 tuple
。
我正在努力做的是创建一个模板化的 class 可以存储元数据,即一组数据。我事先不知道使用什么类型,以及会有多少。
基本上,这就是我想做的
#include<tuple>
template<typename... Data>
class Base{
private:
std::tuple<Data...> mydata;
public:
Base{Data... data):
mydata(data...){}
void set_data(Data... data){
mydata = std::tie(data...)
}
此示例正在运行...但依赖于 tuple
。我知道我可以在没有 tuple
的情况下使用 ArgumentPack
做类似的事情。但是,我不熟悉。
到目前为止,我考虑过使用 struct
来存储我的数据,因为这是我所知道的唯一一种存储不同类型的方法。所以我应该看起来像这样:
template<typename typename<...> class ArgumentPack, typename... Data>
class Base{
private:
struct mydata{
//Something here
};
public:
Base(Data... data){
//assign data into mydata struct
}
void set_data(Data... data){
//???
}
mydata get_data(){
//???
}
如果您的类型全都不同且不是原始类型,您可能会通过继承逃脱:
template <typename... Data>
class Base : Data...
{
};
否则,您应该使用提供 tuple
的库或实现您自己的库。例如boost::tuple
.
从理论上讲,您可以通过提供额外的包装器在 Vittorio 的方法上构建稍微复杂一点的结构。这实际上将允许相同类型和原始类型的多个数据。该方法的 sketch(使用 c++14 来做 index_sequence
的东西,但是 can be reimplemented in c++11 without std
as well):
#include <utility>
#include <iostream>
template <class... Ts>
struct Pack {};
template <std::size_t, class T>
struct Wrapper {
T t;
Wrapper(T t): t(t) { }
};
template <class... Ts>
struct Foo: Foo<Pack<Ts...>, std::make_index_sequence<sizeof...(Ts)>> {
using Foo<Pack<Ts...>, std::make_index_sequence<sizeof...(Ts)>>::Foo;
};
template <class... Ts, std::size_t... Is>
struct Foo<Pack<Ts...>, std::index_sequence<Is...>>: Wrapper<Is, Ts>... {
Foo(Ts... ts):Wrapper<Is, Ts>(ts)... { }
void set_data(Ts... ts) {
this->~Foo();
new (this) Foo (ts...);
}
template <std::size_t I, class T>
static T& get_data_impl(Wrapper<I, T>* th) {
return th->t;
}
template <std::size_t I>
auto get_data() -> decltype(get_data_impl<I>(this)) {
return get_data_impl<I>(this);
}
};
int main() {
Foo<int, float, int> foo(1, 2.0f, 3);
foo.set_data(3, 2, 1);
std::cout << foo.get_data<2>() << std::endl;
}
我正在从事一个非常特殊的项目,因为我无法使用所有 C++11 功能。特别是,我有 variadics
模板但没有 tuple
。
我正在努力做的是创建一个模板化的 class 可以存储元数据,即一组数据。我事先不知道使用什么类型,以及会有多少。
基本上,这就是我想做的
#include<tuple>
template<typename... Data>
class Base{
private:
std::tuple<Data...> mydata;
public:
Base{Data... data):
mydata(data...){}
void set_data(Data... data){
mydata = std::tie(data...)
}
此示例正在运行...但依赖于 tuple
。我知道我可以在没有 tuple
的情况下使用 ArgumentPack
做类似的事情。但是,我不熟悉。
到目前为止,我考虑过使用 struct
来存储我的数据,因为这是我所知道的唯一一种存储不同类型的方法。所以我应该看起来像这样:
template<typename typename<...> class ArgumentPack, typename... Data>
class Base{
private:
struct mydata{
//Something here
};
public:
Base(Data... data){
//assign data into mydata struct
}
void set_data(Data... data){
//???
}
mydata get_data(){
//???
}
如果您的类型全都不同且不是原始类型,您可能会通过继承逃脱:
template <typename... Data>
class Base : Data...
{
};
否则,您应该使用提供 tuple
的库或实现您自己的库。例如boost::tuple
.
从理论上讲,您可以通过提供额外的包装器在 Vittorio 的方法上构建稍微复杂一点的结构。这实际上将允许相同类型和原始类型的多个数据。该方法的 sketch(使用 c++14 来做 index_sequence
的东西,但是 can be reimplemented in c++11 without std
as well):
#include <utility>
#include <iostream>
template <class... Ts>
struct Pack {};
template <std::size_t, class T>
struct Wrapper {
T t;
Wrapper(T t): t(t) { }
};
template <class... Ts>
struct Foo: Foo<Pack<Ts...>, std::make_index_sequence<sizeof...(Ts)>> {
using Foo<Pack<Ts...>, std::make_index_sequence<sizeof...(Ts)>>::Foo;
};
template <class... Ts, std::size_t... Is>
struct Foo<Pack<Ts...>, std::index_sequence<Is...>>: Wrapper<Is, Ts>... {
Foo(Ts... ts):Wrapper<Is, Ts>(ts)... { }
void set_data(Ts... ts) {
this->~Foo();
new (this) Foo (ts...);
}
template <std::size_t I, class T>
static T& get_data_impl(Wrapper<I, T>* th) {
return th->t;
}
template <std::size_t I>
auto get_data() -> decltype(get_data_impl<I>(this)) {
return get_data_impl<I>(this);
}
};
int main() {
Foo<int, float, int> foo(1, 2.0f, 3);
foo.set_data(3, 2, 1);
std::cout << foo.get_data<2>() << std::endl;
}