【问题标题】:Can a parameter pack in function template be followed by another parameter which depends on the return type?函数模板中的参数包可以后跟另一个取决于返回类型的参数吗?
【发布时间】:2021-11-04 14:41:07
【问题描述】:

我有一个模板类型参数跟随参数包的函数。它看起来像这样:

template<typename...Args, typename T>
T* default_factory_func()
{
    return new T;
}

Visual C++ 编译器以错误 C3547: template parameter 'T' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'default_factory_func' 拒绝它。

但是,我尝试了 Compiler Explorer 上可用的各种版本的 GCC(从 4.4.7 开始)和 clang(从 3.1 开始),它们都可以很好地编译此类代码。

// this code is just a minimal example condensed
// from a much more complex codebase
template<typename T>
T* construct(T* (*factory_func)())
{
    return factory_func();
}

template<typename...Args, typename T>
T* default_factory_func() // C3547 on this line
{
    return new T(Args()...);
}

struct some_class {
    some_class(int, int, int) {}
};

int main()
{
    construct<some_class>(
        default_factory_func<int,int,int>
    );
}

这是 MSVC 的一些怪癖还是标准不允许?

【问题讨论】:

    标签: c++ visual-c++ variadic-templates


    【解决方案1】:

    我认为这里的标准很混乱(如果还没有问题,可能需要一个问题)。

    函数模板的模板形参包后面不应有另一个模板形参,除非该模板形参可以从函数模板的形参类型列表([dcl.fct])推导出来或具有默认实参

    • 同时,default_factory_func 的类型可以(可以说)根据[temp.deduct.funcaddr] 推断出来,因为当您通过&amp;default_factory_func&lt;int,int,int&gt; 时,您正试图匹配some_class*(*)(void) 的目标类型

    模板参数可以从获取重载集地址时指定的类型推导出来。如果有目标,则将函数模板的函数类型和目标类型作为P和A的类型,按照[temp.deduct.type]中的描述进行推演。否则,对类型 P 和 A 的空集进行推导

    (感谢n.m. 在他们的now-deleted-answer 中指出第二个)

    我认为最安全的选择是通过重新排序模板参数来避免违反第一条规则:

    template<class T, typename...Args>
    T* default_factory_func()
    {
        return new T(Args()...);
    }
    

    然后显式地转换你的函数指针来解决重载问题:

    auto foo = construct(
        static_cast<some_class*(*)()>(default_factory_func<some_class, int, int, int>)
    );
    

    Live Code

    (在 gcc/clang/和 msvc 上编译最新)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-09
      • 2012-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-09
      • 2012-10-25
      相关资源
      最近更新 更多