【问题标题】:g++ fails to resolve template function overloadg++ 无法解决模板函数重载
【发布时间】:2019-10-11 16:15:39
【问题描述】:

使用以下代码 g++ 失败:

template <typename X = int, typename T, typename ...R>
    inline void func(const T&, R...) {}

template <typename T>
    struct S {};

template <typename X = int, typename T, typename ...R>
    inline void func(const S<T>&, R...) {}

int main() {
    func(42);
    func(S<int>()); // OK
    func(S<int>(), 1); // NOK
    func<int>(S<int>(), 1); // NOK
}

与:

<source>: In function 'int main()':
<source>:13:21: error: call of overloaded 'func(S<int>, int)' is ambiguous
     func(S<int>(), 1); // NOK
                     ^
<source>:13:21: note: candidates are:
<source>:2:17: note: void func(const T&, R ...) [with X = int; T = S<int>; R = {int}]
     inline void func(const T&, R...) {}
                 ^
<source>:8:17: note: void func(const S<T>&, R ...) [with X = int; T = int; R = {int}]
     inline void func(const S<T>&, R...) {}
                 ^
<source>:14:26: error: call of overloaded 'func(S<int>, int)' is ambiguous
     func<int>(S<int>(), 1); // NOK
                          ^
...

可通过 gcc v4.8.1 和 v9.1 重现。使用 clang(v3.0.0 和 v8.0.0)、icc(v13.0.1 和 v19.0.1)、msvc(v19.14 和 v19.20)编译。
代码有效还是 gcc 中的错误?

编辑:谢谢大家,您的反馈对我很有帮助。仅供参考,bug 90642 已提交;期待一个明确的答案。

【问题讨论】:

  • C++ 中没有函数模板的部分特化。只有完全专业化和重载。
  • 你没有专门化这个函数,你重载了它。并且编译器无法区分您传递的参数的两个重载。
  • 谢谢,我的意思是 gcc 没有专业化。我明白你的意思,但是为什么 func(S()) 可以而 func(S(), 1) 不行?
  • fti clang 编译 gcc 不会,直播:godbolt.org/z/p1HsRC
  • 对我来说看起来像一个错误。如果您删除无用和无关紧要的typename X = int,它会编译。没有理由为什么一个应该有效而另一个不应该。

标签: c++ c++11 gcc language-lawyer variadic-templates


【解决方案1】:

有趣的问题。我想你在这里遇到的是overload resolution,更具体地说是partial ordering rules for template specialization

我引用:

非正式地,“A 比 B 更专业”的意思是“A 接受的类型比 B 少”。

我认为编译该clang是正确的,结果应该是第二个候选人

template <typename X = int, typename T, typename ...R>
    inline void func(const S<T>& t, R... p) {}

因为如果第一个参数不是S&lt;T&gt; 类型,它就不再可行,因此更加专业化。

【讨论】:

  • 你认为值得填一个 bug 吗?
  • 我也不是 100% 确定。我认为至少值得对正确的行为有另一种看法;)
  • @oknenavin 我也认为这是一个错误。也许与这个有关:gcc.gnu.org/bugzilla/show_bug.cgi?id=41958 但仍然是一个不同的。如果没有默认的模板参数,该错误就会消失。
  • @Oliv 谢谢。我从一开始就认为这是一个错误,但这是一个复杂的主题,我不确定。我在改进现有代码库 (github.com/oknenavin/cxon) 时发现了这一点,不幸的是,这个默认模板参数是接口的一部分。我要补一个bug,但我还在等账号(gcc/bugzilla)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-23
  • 1970-01-01
相关资源
最近更新 更多