14

示例代码:为什么可变参数函数不能“吃”C++ 11中的列表初始化参数?

#include <unordered_map> 

int main() { 
    std::unordered_map<int, std::pair<int, int>> map; 

    map.emplace(1, {1, 1}); 

    return 0; 
} 

emplace()有签名,如:

template <class... _Args> 
pair<iterator, bool> emplace(_Args&&... __args); 

gcc说,功能expectes 0参数 - 2提供的。 clang表示函数需要1个参数 - 2提供。

我甚至不明白 - 这个代码有什么问题?

回答

12

问题是{1, 1}不是一个表达式,也没有类型。由于它没有类型,因此无法推导到模板参数列表中。它们都不是正确的,因为这个问题与提供的参数数量无关。

+0

'map.emplace(1,std :: pair {1,1})'的作品,不是吗? – Massa

+0

@Jefffrey:不,“{...}”不是一个表达式。第一个是“自动扣减”的特殊框架,它本来不应该存在(并且希望在未来的某个时候可能会被删除),第二个是从braced-init-list中构建的。 – Xeo

+0

@Massa:是的,这就足够了。 – Puppy

7

我甚至不明白 - 这个代码有什么问题?

由于某些不清楚的原因,初始化器列表参数是一个未推导的上下文,请参阅initializer_list and template type deduction。这是因为C++ 11标准的§14.8.2.5/5这样说。我不知道这个看似不一致,违反直觉的行为的理由要么,但我们并不孤单:

至于你的情况,也许最简单的修复方法是:

map.emplace(1, std::make_pair(1, 1)); 
+0

原因并不明显 - 告诉我,什么样的'initializer_list'应该是{1,“hi”}'? – Xeo

+2

@Xeo我没有得到你的例子。 'auto x = {1,“hi”};'也是编译时错误,所以你试图创建什么? – Ali

+0

@Xeo我想如果有的话,原因一定是别的。我的猜测是允许对函数模板参数进行这种推导可能会适得其反。虽然,我没有拿出一个例子。 – Ali

相关问题