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

时间:2018-07-16 07:54:19

标签: c++ c++11 stl stdvector

在通过函数时,常量单元素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 single element vector initialization in a function call

3 个答案:

答案 0 :(得分:6)

您需要另一个重载,将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上进行操作

答案 1 :(得分:5)

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

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

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

答案 2 :(得分:3)

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

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

这样,调用

foo({3});

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

void fooImpl(int a)
{
   std::printf("integer thing\n");
}

template <class Int> void foo(Int&& a)
{
   fooImpl(std::forward<Int>(a));
}

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