【问题标题】:g++ and clang++ different behaviour inferring the template return type of a functiong++ 和 clang++ 推断函数模板返回类型的不同行为
【发布时间】:2018-01-06 01:44:16
【问题描述】:

另一个“在 g++ 和 clang++ 之间谁是对的?” C++ 标准大师的问题。

下面的程序

#include <iostream>

void foo (int v)
 { std::cout << "foo(), int version (" << v << ')' << std::endl; }

void foo (double v)
 { std::cout << "foo(), double version (" << v << ')' << std::endl; }

template <typename T, typename R>
void bar (T v, R(*fn)(T))
 { fn(v); }

int main ()
 { bar(1, foo); }

使用 g++(6.3.0,也可以使用 Wandbox 的 8.0.0)编译和运行,但是使用 clang++(3.9.1,但也可以使用 Wandbox 的 6.0.0)编译它我得到以下错误

tmp_002-11,14,gcc,clang.cpp:29:4: error: no matching function for call to 'bar'
 { bar(1, foo); }
   ^~~
tmp_002-11,14,gcc,clang.cpp:25:6: note: candidate template ignored: couldn't
      infer template argument 'R'
void bar (T v, R(*fn)(T))
     ^
1 error generated.

像往常一样,问题是:谁是对的? g++ 还是 clang++?

【问题讨论】:

  • 返回类型不是函数签名的一部分。仍然似乎违反直觉。我会使用 std:: 函数,所以这里也可以使用 lambda 和仿函数。
  • fooT 被修复之前是模棱两可的。固定T后,R应该可以推演,但我认为推演是一次性完成的。
  • @kamikaze 已经可以传递非捕获 lambda。话虽如此,使用模板参数会更好。
  • void bar (R(*fn)(T), T v) 都无法编译的事实让我觉得 clang 是对的。
  • clang 是对的。重载决议出现在模板推导之后。 gcc 太热心了。

标签: c++ templates g++ type-inference clang++


【解决方案1】:

Clang 是正确的,但有一个微妙的原因:在模板推导期间允许重载集,但 deduction on that one argument 必须能够选择其中一个来推导任何内容。 (如果零匹配,则整体推导失败;如果多个匹配,则推导忽略该论点。)这里,foos 都匹配 R(*fn)(T),因此不能从该论点推导 R(即使它们都将同意),因此根本不同意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2018-07-12
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    相关资源
    最近更新 更多