- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
考虑 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/
我目前正在实现一个通用事件类。事件处理程序有一个发送者参数和可变数量的事件参数。所以事件类的声明如下: template class event; 为了允许某些实现细节,我需要事件的 CRTP,如下所
我需要实现对实现相同接口(interface)的对象 vector 的高效访问。直到现在,我一直在使用带有虚函数的继承:接口(interface)被定义为具有纯虚函数的抽象类,每个对象类都实现了虚函数
在CRTP ,基类可以使用派生类的函数和变量。但是,派生类的类型不能直接被基类使用,见下面代码: #include template class A { public: //using S
我创建了一个模板类,只要发生实例化,它就会触发运行时文本输出: template struct verbose { verbose() { std::cout str
假设我有一个用于矩阵的 CRTP 模板类 template class MatrixBase{ private: //... public: Derived some_function
我已经阅读了很多关于 Curiously Recurring Template Pattern 的帖子而且我仍然不明白为什么我不想只使用模板编程来使用它。 下面是一个从维基百科稍作修改的例子: tem
请帮我解决以下问题: 我有一个类声明为: template class Rim : /* Derive from GenericComponent Design perspective u
有没有办法从 CRTP 基类查询派生类的内容,与 SFINAE 一起使用来启用或禁用基类方法? 我想要完成的可能如下所示: template struct base { struct foo
我有兴趣了解 CRTP。我想为引擎实现一个组件系统,我不想访问组件统一风格 GetComponent("withThisName"); 而是在编译时(虚幻风格) GetComponent(); 虽然实
让我们考虑一个用于打印派生类的 CRTP 模板类 Print: template struct Print { auto print() const -> void; auto se
最近我一直在摆弄模板并偶然发现了以下问题。我正在像这样实现 CRTP 模式: template struct protocol_object { ... }; struct data_obje
我正在尝试在固定大小的缓冲区中构建一条消息,我的图书馆的用户会在其中提供一些数据。我曾经通过给用户一个指向缓冲区的指针并让他们写入它,并通过引用他们写入的字节数来设置一个 size_t 参数来做到这一
我刚刚遇到 CRTP 的问题,我不能在基类和派生类中使用相同的方法名称(具有不同的签名)。重现此问题的示例如下: template struct Base { void foo(){}
考虑以下代码: #include #include #include struct BaseClass { static int identifier() { stati
我有一个纯虚类接口(interface): class Interface { public: virtual ~Interface() noexcept; virtual voi
任何人都可以向我解释为什么 base::blah(string str) 的签名必须是一个字符串而不是引用一个字符串。如果它是一个字符串,编译器会出现以下错误。是因为在模板实例化时编译器拒绝任何隐式转
我遇到了以下代码(存储在 crtp.cc 中)的编译器相关问题: #include #include #include template class AlgebraicVectorExpres
在我的一个项目中,我使用与此处的答案 1 相同的 CRTP 方法(源自 enable_crtp):How do I pass template parameters to a CRTP? 但是我也需要
我目前正在使用 C++ 模板处理 CRTP 模式。在摆弄 visual studio 时,我发现了几种派生类可以调用函数的基类实现的方式/方法。下面是我正在使用的代码以及 3 行注释掉的代码,显示了如
我想创建一个模板类,为类提供通用方法,使其具有成员 m_Type,指定继承类提供的某种类型。考虑一下: template struct TypeAttribute { T m_Type; };
我是一名优秀的程序员,十分优秀!