【发布时间】:2020-04-21 17:24:50
【问题描述】:
考虑下面的代码
#include <functional>
template<class ResultType, class ... Args>
void Foo( std::function<ResultType(Args...)> ) {}
void Dummy(int) {}
int main()
{
Foo<void, int> ( std::function<void(int)>( Dummy ) ); // OK, no deduction and no conversion
Foo( std::function<void(int)>( Dummy ) ); // OK, template argument deduction
Foo<void, int>( Dummy ); // Compile error
}
在第三个中,我理解不能进行模板推导,这就是显式指定模板参数的原因。 但是为什么没有从void (*)(int) 到std::function<void(int)> 的显式转换呢?
我查找了答案,但这些是关于模棱两可的重载解决方案或模板推导,而不是相关主题。
Isn't the template argument (the signature) of std::function part of its type?
Template type deduction with std::function
Implicit conversions with std::function
然后我尝试使用自己的模板类而不是 std::function 进行测试。
// Variadic template class
template<class ... T>
class Bar
{
public:
// Non-explicit ctor, an int can go through implicit conversion
Bar(int) {}
};
// A template function
template<class T>
void Xoo( Bar<T> ) {}
// Same, but this one has a variadic template
template<class ... T>
void Yoo( Bar<T...> ) {}
int main()
{
Xoo( Bar<bool>( 100 ) ); //OK, argument deduction
Xoo<bool>( 100 ); //OK, implicit conversion
Yoo( Bar<bool>( 100 ) ); //OK, argument deduction
Yoo<bool>( 100 ); // Not ok... ?
}
GCC 9.2.0 的输出
prog.cc: In function 'int main()':
prog.cc:23:19: error: no matching function for call to 'Yoo<bool>(int)'
23 | Yoo<bool>( 100 ); // Not ok... ?
| ^
prog.cc:16:6: note: candidate: 'template<class ... T> void Yoo(Bar<T ...>)'
16 | void Yoo( Bar<T...> ) {}
| ^~~
prog.cc:16:6: note: template argument deduction/substitution failed:
prog.cc:23:19: note: mismatched types 'Bar<T ...>' and 'int'
23 | Yoo<bool>( 100 ); // Not ok... ?
| ^
clang 9.0.0 的输出
prog.cc:23:4: error: no matching function for call to 'Yoo'
Yoo<bool>( 100 ); // Not ok... ?
^~~~~~~~~
prog.cc:16:6: note: candidate template ignored: could not match 'Bar<bool, type-parameter-0-0...>' against 'int'
void Yoo( Bar<T...> ) {}
^
1 error generated.
为什么,如果函数具有可变参数模板,则不会进行隐式转换(即使显式指定了模板参数)? 我回到 std::function ,果然,如果函数没有可变参数模板,它就可以工作。
#include <functional>
// Not variadic this time
template<class ResultType, class Arg>
void Goo( std::function<ResultType(Arg)> ) {}
void Dummy(int) {}
int main()
{
Goo<void, int> ( Dummy ); // Ok this time
}
有趣的是,下面的修改使它可以在 clang 中编译
[...]
// Same, but this one has a variadic template
template<class ... T>
void Yoo( Bar<T..., bool> ) {}
// ^^^^
// An extra template for Bar makes implicit conversion
// work for some reason
[...]
我尝试寻找更多与可变参数模板相关的答案,但要么没有关于这个特定主题,要么太超前,我现在无法理解。
How to overload variadic templates when they're not the last argument
Template parameter pack deduction when not passed as last parameter
【问题讨论】:
-
请注意,这会在 MSVC 中编译,但智能感知会显示红色曲线。
-
@P.Rodriguez 在这里回答:stackoverflow.com/a/59578078/5632316
-
@KaenbyouRin 是的,这正是我要找的。谢谢:)
标签: c++ templates variadic-templates variadic-functions implicit-conversion