用一个元素强制std :: vector重载而不是列表上的int重载 [英] Forcing std::vector overload instead of int overload on list with one element

查看:130
本文介绍了用一个元素强制std :: vector重载而不是列表上的int重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

#include <iostream>
#include <vector>

void f(std::vector<int> v) {std::cout << __PRETTY_FUNCTION__ << std::endl;}
void f(int n) {std::cout << __PRETTY_FUNCTION__ << std::endl;}

int main()
{
    f({42}); // the int overload is being picked up
}

在Coliru上直播

我很惊讶地意识到在这种情况下int重载被接收,即程序的输出是:

I was a bit surprised to realize that in this case the int overload is being picked up, i.e. the output of the program is:

void f(int)

void f(int)

有警告

警告:在标量初始值设定项[-Wbraced-scalar-init] f({42})处加括号;

warning: braces around scalar initializer [-Wbraced-scalar-init] f({42});

当然,只有当我将一个1元素的列表作为参数传递时,才会发生这种情况,否则会拾取std::vector重载.

Of course this happens only when I pass a 1-element list as an argument, otherwise the std::vector overload is being picked up.

为什么将{42}视为标量而不是初始化列表?有没有办法强迫编译器即使在1个元素的列表上也选择std::vector重载(没有显式构造std::vector<int>{42})?

Why is {42} treated like a scalar and not like a init-list? Is there any way of forcing the compiler to pick the std::vector overload (without explicitly constructing std::vector<int>{42}) even on 1-element lists?

PS:std::vector具有init-list构造函数

PS: The std::vector has an init-list constructor

vector(std::initializer_list<T> init, const Allocator& alloc = Allocator());

请参见 cppreference 中的(7).

推荐答案

带括号的初始化程序没有类型,我们不能说{42}intstd::initializer_list<int>.当将其用作参数时,重载解析的特殊规则适用于重载的函数调用.

Braced initializer has no type, we can't say {42} is an int or std::initializer_list<int>. When it's used as an argument, special rules for overload resolution will be applied for overloaded function call.

(重点是我的)

  • 否则,如果参数类型不是类并且初始化器列表具有一个元素,则隐式转换序列是将元素转换为参数类型所需的 >
  • Otherwise, if the parameter type is not a class and the initializer list has one element, the implicit conversion sequence is the one required to convert the element to the parameter type

{42}只有一个类型为int的元素,因此它与重载void f(int)完全匹配.对于void f(std::vector<int>),需要用户定义的转换.因此,void f(int)将在此处显示.

{42} has only one element with type int, then it's exact match for the overload void f(int). While for void f(std::vector<int>) a user-defined conversion is needed. So void f(int) will be picked up here.

有没有办法强迫编译器选择std::vector重载(即使在1元素列表上也没有显式构造std::vector<int>{42})?

Is there any way of forcing the compiler to pick the std::vector overload (without explicitly constructing std::vector<int>{42}) even on 1-element lists?

一个概括的说法是,您可以放一些大括号以强制编译器构造std::initializer_list<int>,然后选择void f(std::vector<int>):

As a wordaround, you can put additional braces to force the compiler construct a std::initializer_list<int> and then pick up void f(std::vector<int>):

f({{42}});

直播

这篇关于用一个元素强制std :: vector重载而不是列表上的int重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆