为什么这段代码用gcc编译而不用clang编译

30 c++ g++ c++11 clang++

这段代码与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;
}
Run Code Online (Sandbox Code Playgroud)

错误:

> 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.
Run Code Online (Sandbox Code Playgroud)

Cha*_*uth 4

我相信这段代码是不正确的。在这种情况下,函数参数 toLog不能用于模板参数推导,因为参数是非推导上下文。

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

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

p5.5.3 说:

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

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

可以说,因为这不是一个过载集,所以这可能是将来允许的事情,但我读到的标准并不保证这种技术会起作用。