捕获可变参数模板化参数的模板参数
Capture template parameter of variadic templated arguments
我有以下(不完整,不起作用(定义:
template<typename T, std::function<Args(Context&)>... Funcs>
struct constructor
{
T construct(Context& ctx)
{
return T(Funcs(ctx)...);
}
};
我想要的是一个模板化类 - 第一个参数是构造类型,以下都是要调用的函数,带有 std::function
s 的用户模板,然后调用这些模板以生成类型 T
的构造函数的值。
我认为没有可能使此代码工作,除了捕获函数的返回类型之外。我希望用户像这样使用它:
std::function<int(Context&)> ind = [](Context&) {return 2;};
Constructor<int, ind> c;
// c.construct(...) returns 2 by calling the constructor int(int) with argument
// ind(ctx) - which returns 2.
这可能大致是您要查找的内容。请记住,std::function
不能是模板参数。
template <typename R> using Generator = std::function<R (Context&)>;
template <typename T, typename Generators, std::size_t... Is>
T constructImpl(Context& ctx, const Generators& generators,
std::index_sequence<Is...>) {
return T(std::get<Is>(generators)(ctx)...);
}
template <typename T, typename... Args>
class Constructor {
std::tuple<Generator<Args>...> generators;
public:
Constructor(Generator<Args>... generators)
: generators(std::move(generators)...)
{}
T construct(Context& ctx) {
return constructImpl<T>(ctx, generators,
std::index_sequence_for<Args...>());
}
};
用法:
Constructor<int, int> c([](Context&) { return 2; });
int i = c.construct(context);
assert(i == 2);
类型不能依赖于运行时数据。
调用std::function<X(Y)>
需要运行时数据。 所以你的类型不能依赖于std::function<X(Y)>
,所以类型不能用作模板参数。
现在,它可以依赖于指向全局对象的指针:有趣的是,就C++而言,这不是运行时状态。
因此,您的设计从根本上是有缺陷的。
如果你想要一个返回 2 的函数,这有效:
template<class...ignored>
struct Constructor {
template<class... also_ignored>
Constructor(also_ignored&&...) {}
template<class... also_ignored>
int construct(also_ignored&&...) { return 2; }
};
这将通过您的 OP 中描述的单元测试,但您无法通过 ind
传递给Constructor
因为它不合法。 但是,将其从类型签名中删除并不重要。
如果您想要更多功率,我们可以这样做:
template<class T, class... Functors>
struct Constructor {
T construct( Context& ctx ) {
return T( Functors{}( ctx )... );
}
};
在这种情况下,您需要无状态函数对象:
struct ind { int operator()(Context&)const{return 2;} };
就像std::map
需要无状态比较对象一样。
如果您的函数对象需要状态,那么您需要存储它们的副本以供Constructor
访问(可能在 Constructor
内(,并且您可能需要元组和索引技巧来存储它们。 ("索引技巧"是一个有用的谷歌(
我认为你的Construct
可以只是一个函数:
template <typename T, typename... Funcs>
T construct(Context& ctx, Funcs... funcs) {
return T(funcs(ctx)...);
}
在您的示例中,其用法可能是:
int x = construct<int>(ctx, [](Context& ) { return 2; });
相关文章:
- 在不传递参数数量且只有3个点的情况下,如何使用变差函数
- 如何使用可变参数模板强制转换每个变体类型
- 关于如何在具有单个参数的变体构造中选择替代方案?
- 调用参数排列不变函数 f(i++, i++)
- 参数归纳与标准::变体
- 模板化回调参数的逆变,如 C# 中的逆变
- 如何在没有参数包的情况下编写变差函数
- 通过具有嵌套类的工厂类获取多个变异类模板参数包
- 获取模板参数的成员变量值列表
- 保留短 lambda 用作函数的中间参数,使用 clang 格式保持不变
- 如何定义变体<x,y,z>提取模板参数的子类型
- 正确对齐内存模板,参数顺序不变
- 递归中不同参数类型的变元模板函数
- 通过函数指针传递给变差函数的参数会更改其值
- 提升预定义为带有参数的全局 lambda 的变体访问者
- 使用可变参数模板参数提升变体访问者
- boost ::变体 - 为什么模板参数比const字符串参数具有更高的优先级
- 将变参数包中的值加载到临时数组中
- 使用额外参数提升变体访客
- 正在将动态数组元素解析为参数?(变音符)