我有以下(不完整,不工作)的定义:
template<typename T, std::function<Args(Context&)>... Funcs>
struct constructor
{
T construct(Context& ctx)
{
return T(Funcs(ctx)...);
}
};
我想要的是一个模板化的类 - 第一个参数是构造类型,所有后面都是要调用的函数,带有std::function
的用户模板然后被调用以生成类型构造函数的值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.
答案 0 :(得分: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);
答案 1 :(得分:1)
类型不能依赖于运行时数据。
调用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
内),您可能需要使用元组和索引技巧来存储它们。 (“索引技巧”是一个有用的谷歌)
答案 2 :(得分:0)
我认为您的Construct
可以只是一个功能:
template <typename T, typename... Funcs>
T construct(Context& ctx, Funcs... funcs) {
return T(funcs(ctx)...);
}
您的示例中的用法可能是:
int x = construct<int>(ctx, [](Context& ) { return 2; });