接受大括号构造对象的可变参数模板列表的函数

时间:2014-10-13 19:39:47

标签: c++ templates c++11 variadic-templates

您好模板元编程专家。

我尝试编写一个(类成员)函数,理想情况下可以将其称为类型不可知映射。

理想情况如下:

foo({"Bar", 42}, {"Baz", "Blargh");

以及:

foo({"Blargh", "Bleh"}, {"Biz", 43.6}, {"Bam", {43, 43, 43}});

然后,类/函数应该能够通过调用在编译时推导出的转换函数来转换这些参数,因此它将在内部以带有字符串作为键和值的std :: map结束。

原因只是语法糖。在我的用例中,如果提供了不受支持的类型,调用者不必担心转换参数并获得编译时错误将非常方便。

如果调用者明确使用make_pair,我已经使它工作:

foo(std::make_pair<std::string, std::chrono::miliseconds>("Time", 42));

但自然这不是很干净,并且绝对不比让调用者将值类型转换为std :: string本身更方便。

我已经尝试使用各种值类型的特化创建我自己的std :: pair类,但是如果我使用大括号初始化程序调用我的编译器(gcc)就无法找到它,就像标准std的情况一样::地图。我的编译器似乎将其视为std :: initializer_list,即使参数具有不同的类型。

我或多或少得出的结论是,即使在C ++ 14标准中,我用C ++也无法尝试,但我并不完全确定。

有没有人对如何解决这个问题有任何想法,或者能够解释为什么在这种情况下这是不可能的?

非常感谢!

修改

示例代码:

template<typename Value, typename... Args>
void foo(const std::pair<std::string, Value>& val, Args... args)
{
  foo(args...);
}

void foo(const std::pair<std::string, int>& val) {}

void foo(){}

像这样调用foo():

foo({"key", 42});

不会扩展模板并且可以正常工作:

foo({"key", 42}, {"another", 53})

无法使用错误进行编译:

no matching function for call to ‘foo(<brace-enclosed initializer list>, <brace-enclosed initializer list>)’

2 个答案:

答案 0 :(得分:0)

我能想象的一个解决方案是使用可变参数模板:

template<typename T, typename U, typename... Rest>
auto foo(T t, U u, Rest... rest){
    //deal with t and u,
    //and call foo(rest...) recursievely
}

答案 1 :(得分:0)

我想以下代码:

template <typename... Ts>
void foo(Ts... ts) {}

foo({1,2}, {3,4});
由于完全相同的原因,

无法编译:

template <typename T>
void foo(T t) {}

foo({1,2});

大括号括号列表根本没有类型,因此无法推断出来。

但是,知道大括号括起来的初始化列表可用于通过非显式构造函数初始化具体类型,并且该编译器能够推导出{{ 1}} T的类型,使用老式可变参数列表的以下代码按预期工作:

std::initializer_list<T>

DEMO