Nic*_*son 20 c++ templates c++11 std-function
采取以下最小例子:
using Type1 = std::function<void(void)>;
template <typename T>
using Type2 = std::function<void(T)>;
Type1 whyDoesThisWork;
Type2<void> andYetThisDoesNot;
Run Code Online (Sandbox Code Playgroud)
如果第二个类型别名,我得到错误"参数可能没有'void'类型".(我使用Xcode 4.5,Clang/c ++ 11/libc ++,OS X 10.7进行了测试.)
我发现这很奇怪:我本来期望Type1并且Type2<void>行为相同.这里发生了什么?有没有办法重写第二类型别名,所以我可以编写Type2<void>并获取std::function<void(void)>而不是错误?
编辑我应该补充一点,我想要的原因是允许以下内容:
template <typename ... T>
using Continuation = std::function<void(T...)>;
auto someFunc = []() -> void {
printf("I'm returning void!\n");
};
Continuation<decltype(someFunc())> c;
Run Code Online (Sandbox Code Playgroud)
Continuation<decltype(someFunc())>成为Continuation<void>,我得到了错误.
Ker*_* SB 12
我没有一个实际的答案,只有我在评论中说的:你不能void作为一个函数类型,如:
int foo(int, char, void, bool, void, void); // nonsense!
Run Code Online (Sandbox Code Playgroud)
我认为T(void)只允许作为C的兼容性符号(它区分声明和原型,与C++非常不同,并且需要能够说"没有参数").
所以,解决方案应该是可变的:
template <typename ...Args> using myType = std::function<void(Args...)>;
Run Code Online (Sandbox Code Playgroud)
这样你就可以正确地没有参数:
myType<> f = []() { std::cout << "Boo\n"; }
Run Code Online (Sandbox Code Playgroud)
Yak*_*ont 12
简短的回答是"模板不是字符串替换". void f(void)只有它是void f()C++中的别名才有意义,以便向后兼容C.
第一步是使用可变参数,如其他地方所述.
第二步是弄清楚如何将void返回的函数映射到......好吧,也许是类似的东西std::function<void()>,或者其他东西.我说也许别的东西,因为与其他情况不同,你不能打电话std::function<void()> foo; foo( []()->void {} );- 这不是真正的延续.
这样的事情可能是:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
};
Run Code Online (Sandbox Code Playgroud)
然后像这样使用它:
auto someFunc = []()->void {};
Continuation<decltype(someFunc())>::type c;
Run Code Online (Sandbox Code Playgroud)
它为您提供所需的类型.你甚至可以添加申请继续:
template<typename T>
struct Continuation
{
typedef std::function<void(T)> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
cont( f(args...) );
}
};
template<>
struct Continuation<void>
{
typedef std::function<void()> type;
template<typename func, typename... Args>
static void Apply( type const& cont, func&& f, Args... args)
{
f(args...);
cont();
}
};
Run Code Online (Sandbox Code Playgroud)
如果传入类型为void或者它是非void类型,则允许您对函数的执行应用延续.
但是,我会问"你为什么要这样做"?
几个答案已经解释了理由.为了增加这些答案,规范说(C++11§8.3.5[dcl.func]/4):
由非依赖类型的单个未命名参数组成的参数列表
void等同于空参数列表.除了这种特殊情况,参数不应具有类型cvvoid.
在您的Type2示例中,Tin void(T)是依赖类型 - 它取决于模板参数.