gpt4 book ai didi

c++ - CRTP与完美转发

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:24:33 31 4
gpt4 key购买 nike

考虑 CRTP 的标准用法,对于某些表达式模板机制,它按值保留其子项:

template <typename T, typename>
struct Expr {};

template <typename T>
struct Cst : Expr<T, Cst<T>>
{
Cst(T value) : value(std::move(value)) {}

private:
T value;
};

template <typename T, typename L, typename R>
struct Add : Expr<T, Add<T, L, R>>
{
Add(L l, R r) : l(std::move(l)), r(std::move(r))

private:
L l; R r;
};

等等

现在,在实现运算符时,我们必须通过引用传递,因为要将参数向下转换为正确的类型。问题是我发现自己实现了 operator+ 的四个(!)版本:

template <typename T, typename L, typename R>
Add<T, L, R> operator+(Expr<T, L>&& l, Expr<T, R>&& r)
{
return Add<T, L, R>(
std::move(static_cast<L&>(l)),
std::move(static_cast<R&>(r)));
}

template <typename T, typename L, typename R>
Add<T, L, R> operator+(const Expr<T, L>& l, Expr<T, R>&& r)
{
return Add<T, L, R>(
static_cast<const L&>(l),
std::move(static_cast<R&>(r)));
}

template <typename T, typename L, typename R>
Add<T, L, R> operator+(Expr<T, L>&& l, const Expr<T, R>& r)
{
return Add<T, L, R>(
std::move(static_cast<L&>(l)),
static_cast<const R&>(r));
}

template <typename T, typename L, typename R>
Add<T, L, R> operator+(const Expr<T, L>& l, const Expr<T, R>& r)
{
return Add<T, L, R>(
static_cast<const L&>(l),
static_cast<const R&>(r));
}

确实,如果目标是尽量减少不必要的复制,就必须区分临时值(可以移动)和左值(必须复制),因此有四个重载。

在 C++03 中,“没问题”:我们一直使用 const 引用和复制,期间。在 C++11 中,我们可以做得更好,这就是我们的目标。

是否有一些技巧可以让我一次编写加法逻辑,或者在这里编写一个宏是我最好的选择(因为其他运算符将重复该逻辑)?

我也乐于接受有关如何使用 C++11 编写表达式模板的其他建议。只需考虑目标是最小化复制,因为存储在终端节点中的值可能是巨大的数字或矩阵(在我的精确情况下,终端节点可能包含几兆字节的插值数据,并且这些对象的复制被禁用 - 因为其他对象,复制是可能的)。

最佳答案

这是另一种编写允许按值传递参数的表达式模板的方法:

template <typename T>
struct Expr : T {
Expr(T value) : T(value) { }
};

template <typename A,typename B>
struct Add {
A a;
B b;

Add(A a,B b) : a(a), b(b) { }
};

template <typename A,typename B>
Expr<Add<A,B> > operator+(Expr<A> a,Expr<B> b)
{
return Expr<Add<A,B> >(Add<A,B>(a,b));
}

有很多隐含拷贝,但我发现编译器在删除它们方面做得非常出色。

为了方便使用常量,您可以编写额外的重载:

template <typename A,typename B>
Expr<Add<Constant<A>,B> > operator+(const A& a,Expr<B> b)
{
return Expr<Add<Constant<A>,B> >(Add<Constant<A>,B>(a,b));
}

template <typename A,typename B>
Expr<Add<A,Constant<B> > > operator+(Expr<A> a,const B& b)
{
return Expr<Add<A,Constant<B> > >(Add<A,Constant<B> >(a,b));
}

其中Constant是类模板,例如:

template <typename T>
struct Constant {
const T& value;
Constant(const T& value) : value(value) { }
};

有很多隐含拷贝,但我发现编译器在删除它们方面做得非常出色。

关于c++ - CRTP与完美转发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11711684/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com