【发布时间】:2017-08-29 20:45:55
【问题描述】:
考虑以下代码:
#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;
}
我明确指定类型是因为 (https://stackoverflow.com/a/40476083):
当参数包没有出现在参数的最后时 声明,它是一个非推断的上下文。非推断上下文意味着 必须明确给出模板参数。
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)>’
现在让我们做一个小改动——让我们删除从本地func 中的int 参数,从而导致模板参数包变为空:
#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;
}
这一次,所有三个编译器都将代码拒绝为不正确。 使用 http://rextester.com/l/cpp_online_compiler_gcc 和本地 Visual Studio 安装进行测试。
问题:
- 第一种情况谁是正确的?
- 如何达到预期的效果 - 即如何显式指定(可能为空)参数包?
【问题讨论】:
-
@Rakete1111 - 在我看来问题 1 是重复的;但是(恕我直言)问题 2 不是。
-
@max66 这两种情况都适用于提供的解决方法 (*testfunc)(sfunc)
-
@ArtemyVysotsky - 你的意思是巴里提出的解决方案吗?我没看到。精彩的!你(和 Rakete1111)是对的:重复。
标签: c++ c++11 templates variadic-templates