use*_*520 7 c++ templates variadic-templates c++11
请考虑以下代码:
#include <iostream>
#include <functional>
template<typename... Args>
void testfunc(const std::function<void (float, Args..., char)>& func)
{
}
int main(int argc, char* argv[])
{
auto func = [](float, int, char) {};
auto sfunc = static_cast<std::function<void (float, int, char)>>(func);
testfunc<int>(sfunc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我明确指定了类型,因为(/sf/answers/2833325841/):
当参数包没有出现在参数声明的最后时,它是一个非推导的上下文.非推断的上下文意味着必须明确给出模板参数.
MSVC成功编译它,而gcc和clang都拒绝代码:
source_file.cpp: In function ‘int main(int, char**)’:
source_file.cpp:14:24: error: no matching function for call to ‘testfunc(std::function<void(float, int, char)>&)’
testfunc<int>(sfunc);
^
source_file.cpp:5:6: note: candidate: template<class ... Args> void testfunc(const std::function<void(float, Args ..., char)>&)
void testfunc(const std::function<void (float, Args..., char)>& func)
^
source_file.cpp:5:6: note: template argument deduction/substitution failed:
source_file.cpp:14:24: note: mismatched types ‘char’ and ‘int’
testfunc<int>(sfunc);
^
source_file.cpp:14:24: note: ‘std::function<void(float, int, char)>’ is not derived from ‘const std::function<void(float, Args ..., char)>’
Run Code Online (Sandbox Code Playgroud)
现在,让我们做一个细微的变化-让我们删除的int
从我们当地的说法func
,从而使模板参数包成为空:
#include <iostream>
#include <functional>
template<typename... Args>
void testfunc(const std::function<void (float, Args..., char)>& func)
{
}
int main(int argc, char* argv[])
{
auto func = [](float, char) {};
auto sfunc = static_cast<std::function<void (float, char)>>(func);
testfunc<>(sfunc);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这一次,所有三个编译器都拒绝代码不正确.使用http://rextester.com/l/cpp_online_compiler_gcc和本地Visual Studio安装进行测试.
问题:
我们可以阻止扣除:
template<typename... Args>
void testfunc(const block_deduction<std::function<void (float, Args..., char)>>& func)
Run Code Online (Sandbox Code Playgroud)
同
template<class T>
struct tag_t{using type=T;};
template<class T>
using block_deduction=typename tag_t<T>::type;
Run Code Online (Sandbox Code Playgroud)
现在Args...
是在一个非演绎的背景下.
你可以做票友事情SFINAE并省略char
然后测试该char
在的结束Args...
,但似乎矫枉过正.
当gcc和clang不同意MSVC时,我会向甜甜圈投注美元,MSVC不对.但我没有标准钻探确认.