【问题标题】:Avoid Conversion from single element vector to primitive type避免从单元素向量转换为原始类型
【发布时间】:2018-12-23 17:14:46
【问题描述】:

通过函数时,我遇到了常量单个元素 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

【问题讨论】:

  • 考虑到这是一个很大的混淆源,只要明确写std::vector,你就没有问题。
  • foo(std::vector&lt;int&gt;({5}));

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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      这样调用

      foo({3});
      

      foo(3) 实例化并调用函数模板时,将认为非模板化函数更匹配。这是因为{3} 是一个std::initializer_list&lt;int&gt;在类型推导的上下文中有一个元素。你也可以像这样重定向到原来的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,这可能是一个理想的使用限制。此外,由于转发中间功能,您应该不太可能遇到性能开销。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-13
        • 1970-01-01
        • 1970-01-01
        • 2017-04-16
        • 2013-06-19
        • 1970-01-01
        • 2014-07-09
        • 1970-01-01
        相关资源
        最近更新 更多