函数模板中的参数包后面可以跟另一个取决于 return 类型的参数吗?
Can a parameter pack in function template be followed by another parameter which depends on the return type?
我有一个函数,其中模板类型参数跟在参数包之后。它看起来像这样:
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 的一些怪癖还是标准不允许的?
我认为这里的标准很混乱(如果尚不存在,可能需要一个问题)。
- 根据 [temp.param]
,default_factory_func
的定义格式错误
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument
- 同时,
default_factory_func
的类型可以(有争议地)根据 [temp.deduct.funcaddr] 推导出来,因为当您传递 &default_factory_func<int,int,int>
Template arguments can be deduced from the type specified when taking the address of an overload set. If there is a target, the function template's function type and the target type are used as the types of P and A, and the deduction is done as described in [temp.deduct.type]. Otherwise, deduction is performed with empty sets of types P and A
(感谢n.m. for pointing this second one out in their 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/and msvc 上编译)
我有一个函数,其中模板类型参数跟在参数包之后。它看起来像这样:
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 的一些怪癖还是标准不允许的?
我认为这里的标准很混乱(如果尚不存在,可能需要一个问题)。
- 根据 [temp.param] ,
default_factory_func
的定义格式错误
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument
- 同时,
default_factory_func
的类型可以(有争议地)根据 [temp.deduct.funcaddr] 推导出来,因为当您传递&default_factory_func<int,int,int>
Template arguments can be deduced from the type specified when taking the address of an overload set. If there is a target, the function template's function type and the target type are used as the types of P and A, and the deduction is done as described in [temp.deduct.type]. Otherwise, deduction is performed with empty sets of types P and A
(感谢n.m. for pointing this second one out in their 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/and msvc 上编译)