避免从单一元素向量转换为基元类型

Avoid Conversion from single element vector to primitive type

本文关键字:类型 转换 向量 单一 元素      更新时间:2023-10-16

我在传递函数时遇到常量单个元素std::vector的问题。当std::vector变量包含单个元素时,C++编译器会自动调用错误的函数。这是C++设计的方针。然而,在这种情况下,有任何明确的方法可以指定。以下是问题的示例

assume i have two overload functions both have the same name "foo"
void foo(const std::vector<int> A)
{
// do vector operator
printf("vector thing");
}

void foo(int a)
{
// do integer operator
printf("integer thing")
}

在一般情况下,这两个函数都被正确地调用

foo({1,2,3});    // print do vector thing
foo( 3 );        // print do integer thing

然而,从c++规则来看。当调用时

foo({5});        // print do integer thing ( I want it to call as vector )

其中一种方法是创建一个可变

std::vector<int> B = { 5 };

为了解决这个问题。

我觉得这个方法有点笨拙。是否有任何方法可以使编译器无效,将{5}视为5并调用foo(int a(。

注意:这是解释问题所在的参考资料函数调用中的c++11单元素矢量初始化

您需要另一个重载,将std::initializer_list作为参数:

void foo(std::initializer_list<int> A)
{
foo(std::vector<int>(A.begin(), A.end()));
}

如果您总是通过直接使用{...}创建向量而不是使用std::vector变量来调用此函数,那么您可以完全消除std::vector过载并直接在std::initializer_list上操作。

否,因为从C++17开始,链接答案上解释的规则仍然有效。

不过,您可以创建一个临时的,而不是一个变量。

foo(std::vector{5});      // C++17 with class type deduction
foo(std::vector<int>{5}); // older versions

消除函数调用歧义的一种方法是将整数重载作为函数模板:

template <class Int> void foo(Int a)
{
std::printf("generalized (maybe integer) thingn");
}

这样,调用

foo({3});

将认为非模板化函数是更好的匹配,而foo(3)实例化并调用函数模板。这是因为{3}是一个std::initializer_list<int>,在类型推导的上下文中有一个元素。您也可以重定向到原始的foo(int a)函数,如下所示:

void fooImpl(int a)
{
std::printf("integer thingn");
}
template <class Int> void foo(Int&& a)
{
fooImpl(std::forward<Int>(a));
}

例如,当使用不可转换为整数的参数调用foo时,这将拒绝编译,这可能是一个理想的使用限制。此外,由于转发中间功能,您不太可能遇到性能开销。