Kyl*_*and 5 c++ lambda variadic-templates c++11 std-function
我想创建一个std::function带有任意签名的简单无操作对象.为此,我创建了两个函数:
template <typename RESULT, typename... ArgsProto>
std::function<RESULT(ArgsProto...)> GetFuncNoOp()
{
// The "default-initialize-and-return" lambda
return [](ArgsProto...)->RESULT { return {}; };
}
template <typename... ArgsProto>
std::function<void(ArgsProto...)> GetFuncNoOp()
{
// The "do-nothing" lambda
return [](ArgsProto...)->void {};
}
Run Code Online (Sandbox Code Playgroud)
这些中的每一个都运行得很好(显然第一个版本可能在RESULT对象中创建未初始化的数据成员,但实际上我认为这不会是一个大问题).但是第二个 - void返回版本是必要的,因为return {}; 永远不会返回void(这将是编译错误),并且它不能被写为第一个的模板特化,因为初始签名是可变参数.
所以我不得不在这两个函数之间进行选择,只实现一个,或给它们不同的名称.但我真正想要的是以std::function这样的方式轻松初始化对象:当被调用时,它们什么也不做,而不是抛出异常.这可能吗?
你太拘泥于牙套了.
template <typename RESULT, typename... ArgsProto>
std::function<RESULT(ArgsProto...)> GetFuncNoOp()
{
// && avoids unnecessary copying. Thanks @Yakk
return [](ArgsProto&&...) { return RESULT(); };
}
Run Code Online (Sandbox Code Playgroud)
我不喜欢必须指定签名。
假设你有一个std::function实施方案,其中std::function<void()>可以接受类型的函数指针int(*)(),这是一个非类型擦除noop可铸造成任何对象std::function:
struct noop {
struct anything {
template<class T>
operator T(){ return {}; }
// optional reference support. Somewhat evil.
template<class T>
operator T&()const{ static T t{}; return t; }
};
template<class...Args>
anything operator()(Args&&...)const{return {};}
};
Run Code Online (Sandbox Code Playgroud)
如果您std::function不支持该转换,我们添加:
template<class...Args>
operator std::function<void(Args...)>() {
return [](auto&&...){};
}
Run Code Online (Sandbox Code Playgroud)
假设您对std::functionSFINAE 友好,应该处理这种情况。
要使用,只需使用noop{}. 如果您真的需要一个返回 noop 的函数,请执行inline noop GetFuncNoop(){ return{}; }.
这样做的一个附带好处是,如果您将 传递noop给非类型擦除操作,我们不会std::function因为什么都不做而获得无意义的开销。
引用支持是邪恶的,因为它创建了一个全局对象并在所有地方传播对它的引用。如果std::function<std::string&()>调用了一个,并string修改了结果,则修改后的字符串将在任何地方使用(并且在使用之间没有任何同步)。加上在不告诉任何人的情况下分配全球资源似乎很粗鲁。
我刚刚=delete的operator T&情况相反,并生成一个编译时错误。
| 归档时间: |
|
| 查看次数: |
2120 次 |
| 最近记录: |