【问题标题】:C++11 ambiguous overload when calling variadic function template调用可变参数函数模板时的 C++11 模棱两可的重载
【发布时间】:2018-09-04 10:09:30
【问题描述】:

尽管我使用显式模板实例化,您能否解释一下为什么我有 error: call of overloaded ‘func(const Test&)’ is ambiguous

#include <iostream>

struct Test {
};

void func(const Test &) {
  std::cout << "By Reference" << std::endl;
}

void func(const Test) {
  std::cout << "By Value" << std::endl;
}

template <typename... TArgs>
void wrap(TArgs... args) {
  func(args...);
}

int main() {
  Test t;
  wrap<const Test &>(t);
  return 0;
};

编辑

模棱两可的原因是两个因素的结合。第一个是在调用func(args...) 中应用的简单重载规则。第二个是简单的函数不能被值和常量引用重载。为确保这一点,可以将调用 wrap&lt;const Test &amp;&gt;(t) 替换为 func(static_cast&lt;const Test &amp;&gt;(t))。错误仍然存​​在。

为了解决这个问题,可以使用func 的函数模板和@lubgr 提供的示例中所示的value vs const 引用模板专业化

感谢大家帮助我揭开这个概念的神秘面纱。

【问题讨论】:

  • 即使不是模板,你的调用也是模棱两可的。
  • 哪部分你不明白?

标签: c++ variadic-templates


【解决方案1】:

出于同样的原因,以下调用是模棱两可的:

#include <iostream>
void foo(int) { std::cout << "val" << std::endl; }
void foo(const int&) { std::cout << "ref" << std::endl; }

int main()
{
  int i = 1;
  foo(i);
}

请参阅here 了解有关该案例的完整讨论。

【讨论】:

    【解决方案2】:

    通过显式实例化 wrap 函数模板,想象编译器在 wrap 实例化中,知道 Targs... 确实是 const Test&amp;。那么应该选择哪个函数重载?它不能更喜欢一个,因为wrap 的模板参数不会传播到普通(非模板)函数。相反,简单的重载规则适用。

    如果您也将func 更改为函数模板,您可以看到差异并解决问题:

    template <class T> void func(T);
    
    template <> void func<const Test&>(const Test&) {
      std::cout << "By Reference" << std::endl;
    }
    
    template <> void func<const Test>(const Test) {
      std::cout << "By Value" << std::endl;
    }
    

    然后,当您明确要求时调用相应的特化。

    template <typename... TArgs>
    void wrap(TArgs... args) {
      func<TArgs...>(args...); // Note, the type is specified here, again.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-09
      • 2011-12-19
      • 2016-12-27
      • 1970-01-01
      • 2021-07-26
      • 2015-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多