是否可以将 CRTP 与本身已模板化的派生 类 一起使用?

Is it possible to use CRTP with derived classes that are themselves templated?

我正在尝试将 CRTP 与派生的 类 一起使用,它们本身是模板化的,并且 运行 会导致我不知道如何修复的编译器错误。

有没有办法做我想做的事?

代码在这里。

#include <iostream>

// Parent class to use in CRTP
template <typename T>
class Singleton {
    public:

    static T& getInstance() {
        Protector p;
        static T instance(p);
        return instance;
    }

    // Singleton pattern - no copying!
    Singleton(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    const Singleton& operator=(const Singleton&) = delete;
    Singleton& operator=(Singleton&&) = delete;

protected: // so only derived classes can construct Singletons
    Singleton() = default;
    struct Protector {};    // avoids having to make Singleton a friend of descendents.
    virtual ~Singleton() = default;
};


// Simple example of using the CRTP, this one compiles and runs as expected
class Counter final : public Singleton<Counter> {
    private:
        int _counter;
    public:
        Counter (Protector) : _counter(0) {std::cout << "Counter Constructor" << std::endl;}
        ~Counter () {std::cout << "Counter Destructor" << std::endl;}
        int inc() {return ++_counter;}
        int dec() {return --_counter;}
        const int operator()() const {return _counter;}
};

// More complex example of using the CRTP. It generates compiler errors
template <typename T>
class TCounter final : public Singleton<TCounter<T>> {
    private:
        T _counter;
    public:
        TCounter (Protector) : _counter(0) {std::cout << "TCounter Constructor" << std::endl;}
        ~TCounter() {std::cout << "TCounter Destructor" << std::endl;}
        T inc() {return ++_counter;}
        T dec() {return --_counter;}
        const T operator()() const {return _counter;}
};

int main () {
    using namespace std;
    Counter& ctr = Counter::getInstance();
    cout << ctr() << ", " << ctr.inc() << ", " << ctr.dec() << endl;

    using FCounter = TCounter<float>;
    FCounter& fctr = FCounter::getInstance();
    cout << fctr() << ", " << fctr.inc() << ", " << fctr.dec() << endl;
    return 0;
}

这里是编译器输出

$ g++ src/goof.cpp -o goof
src/goof.cpp:45:22: error: function definition does not declare parameters
   TCounter (Protector) : _counter(0) {std::cout << "TCounter Constructor" << std::endl;}
                      ^
src/goof.cpp: In instantiation of ‘static T& Singleton<T>::getInstance() [with T = TCounter<float>]’:
src/goof.cpp:58:29:   required from here
src/goof.cpp:10:12: error: no matching function for call to ‘TCounter<float>::TCounter(Singleton<TCounter<float> >::Protector&)’
   static T instance(p);
            ^~~~~~~~
src/goof.cpp:41:7: note: candidate: ‘TCounter<float>::TCounter()’
 class TCounter final : public Singleton<TCounter<T>> {
       ^~~~~~~~
src/goof.cpp:41:7: note:   candidate expects 0 arguments, 1 provided

不明白的地方:

在此先感谢您的帮助。

您需要做的就是手动引导编译器告诉它如何解析 Protector

template <typename T>
class TCounter final : public Singleton<TCounter<T>> {
public:
  using Protector = typename Singleton<TCounter<T>>::Protector;
};