我有一个针对某些结构的辅助基类,它使用 CRTP 来帮助我获取有关它们的一些信息:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
};
Run Code Online (Sandbox Code Playgroud)
我已经在代码库的各个库中使用了使用此定义的结构,并且我希望有一种方法来记录它们。我的第一个想法是这样的:
template <class T>
struct MyHelper
{
size_t size() const { return sizeof(T); }
virtual void print(std::ostream& out) const { out << "(" << sizeof(T) << ")"; }
};
Run Code Online (Sandbox Code Playgroud)
但后来我意识到这行不通,原因有几个 - 其中之一是添加虚拟实际上改变了 POD 数据的大小。
有没有办法在没有 virtual 关键字的情况下让我拥有一个使用上述实现的默认 toStr 方法,除非特定的派生类 T 有一个实现,在这种情况下它会遵循该实现?
我无法让CRTP mixin工作.
这是剥离的实现:
template < typename T >
class AutoSList : public T {
public:
AutoSList() {}
~AutoSList() : _next(nullptr) {}
private:
static T* _head;
static T* _tail;
T* _next;
};
// I really hate this syntax.
template <typename T>
T* AutoSList<T>::_head = nullptr;
template <typename T>
T* AutoSList<T>::_tail = nullptr;
class itsybase : public AutoSList < itsybase >
{
};
Run Code Online (Sandbox Code Playgroud)
我正在使用VS2013并收到以下错误:
error C2504: 'itsybase' : base class undefined
: see reference to class template instantiation 'AutoSList<itsybase>' being compiled
Run Code Online (Sandbox Code Playgroud)
我不知道出了什么问题,有什么建议吗?
我们考虑以下代码:
template<typename T>
struct Base{
};
struct Derived: Base<Derived>{
};
int main() {
Base<Derived>* base_ptr = new Derived();
}
Run Code Online (Sandbox Code Playgroud)
它有效,我的意思是它编译.和类的相同版本:
template<typename T>
class Base{
};
class Derived: Base<Derived>{
};
int main() {
Base<Derived>* base_ptr = new Derived();
//ERROR ‘Base<Derived>’ is an inaccessible base of ‘Derived’
}
Run Code Online (Sandbox Code Playgroud) 虽然虚拟功能在运行时被解析,但CRTP可以像虚函数一样调用子类方法.
据我所知,在析构函数中调用虚函数是不安全的.CRTP也是如此吗?使用CRTP调用子方法是安全还是不安全?
编辑:
如果它不安全,那么多重继承案例呢?例如,
template<typename T, typename V>
struct CRTP {
~CRTP()
{
static_cast<V*>(static_cast<T*>(this))->run();
}
};
struct Run {
void run() { std::cout << "run" << std::endl; }
};
struct A : Run, CRTP<A, Run> {
};
Run Code Online (Sandbox Code Playgroud)
这里,破坏的顺序是A-> CRTP-> Run.在CRTP的析构函数中调用Run函数是否安全?
我正在尝试使用 CRTP 来实现多种迭代器类型的通用功能。如此处 使用带有 CRTP 的内部类所述,不可能将 CRTP 用于内部类,因此我将基本迭代器类移出容器类,并在迭代器的容器内继承它。但我还是得到了
error: invalid use of incomplete type 'class ConcreteIteratorBase<Node<int>, std::iterator_traits<Node<int>*>, std::iterator<std::forward_iterator_tag, Node<int>, long int, Node<int>*, Node<int>&> >'
Run Code Online (Sandbox Code Playgroud)
错误。
这是最小的可重现示例:
#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>
template <typename T>
class NotEqFromEqMixin : public T
{
public:
bool operator!=(T const & other) const
{
return !(static_cast<T const &>(*this) == other);
}
};
template <typename Iterator, typename Traits, typename StdBase>
class IteratorHelperMixin : public NotEqFromEqMixin<Iterator>, public StdBase
{
public: …
Run Code Online (Sandbox Code Playgroud) 请参阅此处的对象计数器示例:为什么它不会从非模板继承.为什么反击应该是模板?class counter
template <typename T>
struct counter
Run Code Online (Sandbox Code Playgroud) 我有一个使用 CRTP 和 C++20 的代码:
template<class Derived>
class Base {
public:
void m() {
static_cast<Derived*>(this)->feature();
}
virtual constexpr void feature() = 0;
}
class BaseImpl: public Base<BaseImpl> {
virtual constexpr void feature() final override { // ... };
}
Run Code Online (Sandbox Code Playgroud)
有没有办法删除vptr
,这样对象就不会占用 8 个字节(对于 x64),而只占用 1 个字节?(因为它从不使用运行时多态性)?
在实际代码中,层次结构要复杂得多,有 2 个vptr
(因此需要 16 个字节)。是否有类似 GCC 或 MSVC 的扩展?
是的,当然,解决方案之一就是删除该virtual
方法。但由于它具有复杂的层次结构,它带来了极其丑陋的错误和不可维护的代码,因为程序员应该通过读取不可读的模板实例化错误来猜测必须实现哪些方法。
整个目标是实现类似 Java 的层次结构(具有接口、覆盖检查等),但具有零成本抽象。
我做了一些实验(探索代码反汇编),编译器完全优化了所有虚拟调用,提供了零成本抽象。除了它将对象扩展为具有vptr
我的代码中从未使用过的 a 。
我发现了类似的东西__declspec(novtable)
,但vptr
仍然占用空间。是的,物体的尺寸尽可能小是极其重要的。