是否可以将 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
不明白的地方:
- 为什么编译器认为候选构造函数采用零参数? (第 41 行)
- 它抱怨我没有提供参数(第 45 行),但是当我这样做时,它输出一个不同的错误 - 在 Protector 之后期待一个 ')'。
在此先感谢您的帮助。
您需要做的就是手动引导编译器告诉它如何解析 Protector
。
template <typename T>
class TCounter final : public Singleton<TCounter<T>> {
public:
using Protector = typename Singleton<TCounter<T>>::Protector;
};
我正在尝试将 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
不明白的地方:
- 为什么编译器认为候选构造函数采用零参数? (第 41 行)
- 它抱怨我没有提供参数(第 45 行),但是当我这样做时,它输出一个不同的错误 - 在 Protector 之后期待一个 ')'。
在此先感谢您的帮助。
您需要做的就是手动引导编译器告诉它如何解析 Protector
。
template <typename T>
class TCounter final : public Singleton<TCounter<T>> {
public:
using Protector = typename Singleton<TCounter<T>>::Protector;
};