可在函数签名中使用的可变类型定义
variadic typedef that can be used in function signature
基本上我只是想包装任何可调用的对象和他们的参数在一个任务对象,可以调用以后。下面是我想到的代码:
假设所有可调用类型都有一个成员类型,就像这样定义的:
template<typename TReturn, typename...TArgs>
struct SomeFunction{
using ArgTypes = TArgs; // won't compile of course
}
任务模板可以这样定义:
template<typename TFunction>
class Task {
public:
Task(TFunction fun, typename TFunction::ArgTypes...args) // won't compile
: fun_(fun), args_(args){}
void operator()()
{
fun_(args_...); // won't compile: workaround 1
}
private:
typename TFunction::ArgTypes... args_; // won't compile: workaround 2
TFunction fun_;
};
问题在于Task的构造函数的定义。有什么办法可以实现吗?当然,我可以将它定义为模板构造函数:
template<typename...TArgs>
Task(TFunction fun, TArgs...args)
但是这样编译器就不会知道TArgs和TFunction::ArgTypes是一样的。因此,当错误的参数传递给它时,错误消息是荒谬的。
解决方案1:c++如何将参数包存储为变量
解决方案2:是否可以"存储";模板参数包而不展开它?
您可以使用std::tuple<TArgs...>
来存储参数并在调用操作符中解压缩它们。如果您想以某种方式在函数类型中定义TArgs
,则应该在这里将它们定义为元组:
template<typename TReturn, typename...TArgs>
struct SomeFunction{
using ArgTypesTuple = std::tuple<TArgs...>;
// ^^^^^^^^^^
}
但是,尽管如此,我认为这是不值得的努力保存参数在你的Task
对象与大量的样板代码…调用操作符将元组中的参数重构/解包为参数列表,看起来有些难看。
更简单的解决方案是创建一个lambda,它在构建Task
对象时捕获参数,它甚至不再需要是模板:
class Task {
public:
template<typename TFunction, typename ...ArgTypes>
Task(TFunction fun, ArgTypes... args)
: fun_([=]{ fun(args...); }) {}
void operator()()
{
fun_();
}
private:
std::function<void()> fun_;
};
你可以做一些改变:
template <typename TReturn, typename...TArgs>
struct SomeFunction{
using ReturnType = TReturn;
using ArgTypes = std::tuple<TArgs...>;
};
For Task
:
template <typename TFunction, typename TupleArg = typename TFunction::ArgTypes>
class Task;
template <typename TFunction, typename... TArgs>
class Task<TFunction, std::tuple<TArgs...>>
{
public:
Task(TFunction fun, TArgs...args) : fun_(fun), args_(args...) {}
void operator()()
{
call(make_index_sequence<sizeof...(TArgs)>{});
}
private:
template <std::size_t ... Is>
void call(index_sequence<Is...>)
{
fun_(std::get<Is>(args_)...);
}
private:
TFunction fun_;
std::tuple<TArgs...> args_;
};
生活例子
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 强枚举类型定义:Clang Bug 还是 C++11 标准不确定性?
- 列表参数的类型定义
- 使用模板化的键类型定义 std::map,该键类型基于作为参数接收的函数
- 关于 C++ 中的函数类型定义
- C++(和 ROS) - 包含与前向声明引用,设置默认值和类型定义
- 将使用/类型定义限制为类范围
- 模板类型定义?
- C++:模板类的类型定义
- 如何对命名空间限定类型进行类型定义?
- 此递归模板类型定义是否有效C++?
- 具有调整对齐方式的类型定义
- C++从抽象类型定义类成员
- 用于C++代码的 API 监视器类型定义 (XML)
- 如何将result_of与函数类型定义一起使用
- 在C++的适当类型定义位置
- 如何根据模板类型定义浮点常量?
- 如何为缺少预定义运算符而不扩展命名空间"std"的标准类型定义运算符>> (istream &, ...)?
- 参数化类的别名(或类型定义)内部类
- 如果我想从类型"T"定义元素的容器(来自 STL),那么"T"必须使用默认构造函数?