这实际上是可行的,具有 c++11 特性。
是的,initializer_list 希望它的所有元素都属于同一类型。诀窍是我们可以创建一个包装类,它可以是static_cast
我们想要的所有类型。这很容易实现:
template <typename... tlist>
class MultiTypeWrapper {
};
template <typename H>
class MultiTypeWrapper<H> {
public:
MultiTypeWrapper() {}
MultiTypeWrapper(const H &value) : value_(value) {}
operator H () const {
return value_;
}
private:
H value_;
};
template <typename H, typename... T>
class MultiTypeWrapper<H, T...>
: public MultiTypeWrapper<T...> {
public:
MultiTypeWrapper() {}
MultiTypeWrapper(const H &value) : value_(value) {}
// If the current constructor does not match the type, pass to its ancestor.
template <typename C>
MultiTypeWrapper(const C &value) : MultiTypeWrapper<T...>(value) {}
operator H () const {
return value_;
}
private:
H value_;
};
使用隐式转换构造函数,我们可以将类似 {1,2.5,'c',4} 的内容传递给 MultiTypeWrapper 类型的 initializer_list(或向量,它隐式转换 initializer_list)。这意味着我们不能编写像下面这样的函数来接受这样的 intializer_list 作为参数:
template <typename... T>
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) {
....
}
我们使用另一个技巧将向量中的每个值转换为其原始类型(请注意,我们在 的定义中提供了隐式转换MultiTypeWrapper
)并将其分配给元组中的相应槽。这就像模板参数的递归:
template <int ind, typename... T>
class helper {
public:
static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) {
std::get<ind>(t) = static_cast<typename std::tuple_element<ind,std::tuple<T...> >::type>(v[ind]);
helper<(ind-1),T...>::set_tuple(t,v);
}
};
template <typename... T>
class helper<0, T...> {
public:
static void set_tuple(std::tuple<T...> &t, const std::vector<MultiTypeWrapper<T...> >& v) {
std::get<0>(t) = static_cast<typename std::tuple_element<0,std::tuple<T...> >::type>(v[0]);
}
};
template <typename... T>
std::tuple<T...> create_tuple(std::vector<unit_test::MultiTypeWrapper<T...> > init) {
std::tuple<T...> res;
helper<sizeof...(T)-1, T...>::set_tuple(res, init);
return res;
}
请注意,我们必须创建帮助程序类,set_tuple
因为 c++ 不支持函数特化。现在,如果我们要测试代码:
auto t = create_tuple<int,double,std::string>({1,2.5,std::string("ABC")});
printf("%d %.2lf %s\n", std::get<0>(t), std::get<1>(t), std::get<2>(t).c_str());
输出将是:
1 2.50 ABC
这是在我的桌面上用 clang 3.2 测试的
希望我的意见有帮助:)