【问题标题】:Why does this code compile with gcc but not with clang为什么这段代码用 gcc 编译而不用 clang
【发布时间】:2016-05-27 22:16:34
【问题描述】:

此代码与 gcc/g++ 和 msvc 完美结合,但不适用于 clang。 一直报找不到Log的匹配函数,这是怎么回事?

#include <iostream>

template <typename Function, typename... Args>
auto Call(Function func, Args&&... args) -> typename std::result_of<Function&(Args&&...)>::type
{
    return func(std::forward<Args>(args)...);
}

template <typename T, typename... Args>
T (*Log( T (*FuncPtr)(Args...) ))(Args...)
{
    return FuncPtr;
}

int main()
{
    auto r = Log(Call<int(int), int>)([](int x){
        return x*10;
    }, 10);
    std::cerr << r << std::endl;
}

错误:

> error: no matching function for call to 'Log'
>     auto r = Log(Call<int(int), int>)([](int x){
>              ^~~ test7.cpp:15:5: note: candidate template ignored: couldn't infer template argument 'T' T (*Log( T (*FuncPtr)(Args...)
> ))(Args...)
>     ^ 1 error generated.

【问题讨论】:

  • 更简单:auto call = Call&lt;int(int), int&gt;; 失败,error: variable 'call' with type 'auto' has incompatible initializer of type '&lt;overloaded function type&gt;'Log 的问题是一个红鲱鱼,问题开始得更早 - 编译器似乎无法确定 Call&lt;int(int), int&gt; 是什么类型。
  • 如果将result_ofdance 替换为decltype(func(args...)),则可以使用
  • 为什么会有一个&符号std::result_of&lt;Function &amp;( ...)&gt;?这对我来说看起来格格不入。
  • 更好的是,将typename std::result_of&lt;...&gt;::type 替换为std::result_of_t&lt;...&gt; 并clang 编译它。这……很奇怪。
  • @ChrisBeck 我扔掉了27918,我们来看看聪明人怎么说。

标签: c++ c++11 g++ clang++


【解决方案1】:

我认为此代码不正确。在这种情况下,Log 的函数参数不能用于模板参数推导,因为该参数是非推导上下文。

从标准中的[temp.deduct.type],p5列出了非推导的上下文,p5.5说:

无法进行实参推导的函数形参 因为关联的函数参数是一个函数,或者是一组 重载函数 (13.4),并且适用以下一项或多项:

p5.5.3 说:

作为参数提供的一组函数包含一个或多个 函数模板。

我的解释是你有一个函数参数,它的函数参数是一个(指向)函数,而该函数是一个函数模板。

可以说,因为这不是一个重载集,所以将来可能会允许这样做,但我认为标准并不保证这种技术会起作用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    • 2012-02-14
    相关资源
    最近更新 更多