[英]How can I access the types in a C++ template parameter pack?
我想构造一个 class ,它表示从I
类型的值到O
类型的值的映射。 我创建了这个界面:
template <typename I, typename O> class Transform {
public:
virtual O transform(I i) = 0;
};
接下来,我想允许Transform
对象组合成一种“管道”转换:
template <typename X, typename Y, typename Z> class MergeTransform : public Transform<X, Z> {
private:
Transform<X, Y> *first;
Transform<Y, Z> *second;
public:
MergeTransform(Transform<X, Y> *first, Transform<Y, Z> *second) {
this->first = first;
this->second = second;
}
Z transform(X x) {
return second->transform(first->transform(x));
}
};
目前困扰我的是试图弄清楚如何使用模板来合并任意数量的转换。 我想做类似的事情
template <typename A, typename B, typename C> Transform<A, C> *merge(Transform<A, B> *t1, Transform<B, C> *t2) {
return new MergeTransform(t1, t2);
}
template <typename A, typename... Bs, typename C> Transform<A, C> *merge(/* what should go here? */) {
// ...
}
但是后来我不知道如何在第二种merge
方法中表示从A->B1, B1->B2, B2->...->Bn, Bn->C
的Transform
列表。 我还考虑让模板参数成为转换本身,即。
/*
* assume A and B are Transforms
*/
template <typename A, typename B> /* some return Transform type here */ *merge(A *a, B *b) {
return new MergeTransform(a, b);
}
template <typename A, typename... Bs, typename C> /* return type */ *merge(A *a, Bs... bs, C *c) {
return merge(merge(a, bs), c);
}
但在不知道 A 和 B Transform
的模板类型的情况下无法定义返回类型。 有没有办法访问这些值? 理想情况下,我可以说
template <Transform<X, Y> A, Transform<Y, Z> B> Transform<X, Z> *merge(A *a, B *b) {
return new MergeTransform(a, b);
}
template <Transform<W, X> A, Transform<?, ?>... Bs, Transform<Y, Z> C> Transform<W, Z> *merge(A *a, Bs... *bs, C *c) {
return merge(merge(a, bs), c);
}
如果merge(a, bs)
的扩展没有返回Transform<X, Y>
,编译器会抛出错误。 做这个的最好方式是什么?
由于滥用运算符重载和折叠表达式 (C++17),您可能会执行类似的操作来链接操作:
template <typename ... Fs>
class Chain
{
private:
template <typename F>
struct CallerWrap
{
F f;
CallerWrap(F f) : f(f) {}
template <typename T>
friend decltype(auto) operator+ (const CallerWrap& callerWrap, T&& x)
{
return callerWrap.f(std::forward<T>(x));
}
};
std::tuple<Fs...> tup;
public:
Chain(Fs... fs) : tup{fs... }{}
template <typename T>
decltype(auto) operator()(T x) const {
return std::apply([&x](auto... fs){ return (CallerWrap{fs} + ... + x); }, tup);
}
};
f1(f2(f3(x)))
没有折叠表达式,但f1 + (f2 + (f3 + x))
(和其他二元运算符)有折叠表达式。 所以我们添加包装器以使用后者并等效于前者。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.