【发布时间】:2014-10-13 19:39:46
【问题描述】:
模板元编程专家您好。
我正在尝试编写一个(类成员)函数,理想情况下可以将其作为参数,称为类型不可知映射。
最好是这样的:
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>)’
【问题讨论】:
-
C++14 肯定会减少很多冗长,例如你可以只写这个
std::make_pair("Time"s, 42ms)而不是你写的。好多了。 -
你有没有尝试实现一些东西?
-
@Nawaz:这实际上是一个好点。另外,你的例子让我觉得除了简单类型之外的任何东西的转换可能都不是一个很好的设计。不应由被调用者决定如何转换,例如。字符串的时间戳。我仍然觉得知道是否可以这样做很有趣。
-
没有模板
void foo(Ts... a){ bar({rest...}); } 工作?
标签: c++ templates c++11 variadic-templates