How to avoid errors while using CRTP?
In C++0x you have a simple solution. I don't know whether it is implemented in MSVC10 however.
template <typename T>
struct base
{
private:
~base() {}
friend T;
};
// Doesn't compile (base class destructor is private)
struct foo : base<bar> { ... };
How to secure CRTP against providing wrong superclass?
Make Base
's destructor private, and then make Derived
a friend of Base<Derived>
:
template <class Derived>
class Base {
private: ~Base() = default;
friend Derived;
};
class Derived : public Base<Derived> {
};
This does not actually make doing
class AnotherDerived : public Base<Derived> {
};
illegal, but any attempt to actually construct an AnotherDerived
will fail.
Various errors with CRTP (C++)
You need to implement your specialized functions as this:
template<>
const string& Entity<Client>::name() const {
return _name;
}
template<>
Client& Entity<Client>::name(const string& name) {
_name = name;
return *This();
}
and also add public inheritance:
class Client : public Entity<Client>
so you can access name()
.
If you want generic implementations:
template<class x>
const string& Entity<x>::name() const {
return _name;
}
template<class x>
x& Entity<x>::name(const string& name) {
_name = name;
return *This();
}
Prevent user from deriving from incorrect CRTP base
1) make all constructors of Base private (if there are no constructors, add one)
2) declare Derived template parameter as friend of Base
template <class Derived>
class Base
{
private:
Base(){}; // prevent undesirable inheritance making ctor private
friend Derived; // allow inheritance for Derived
public :
void call ()
{
static_cast<Derived *>(this)->call_impl();
}
};
After this it would be impossible to create any instances of the wrong inherited D2.
CRTP compiling error
Try making it a constexpr function instead. The way you have it setup now attempts to access an incomplete type.
Since a templated member function will only be initialized upon first being used, type A
will be fully defined by that point.
#include <iostream>
template <typename Derived>
struct CRTP {
static constexpr int num() { return Derived::value + 1; }
};
struct A : CRTP<A> {
static constexpr int value = 5;
};
int main()
{
std::cout << A::num();
return 0;
}
See it live here
Compile errors for simple CRTP case with dependent types
Change the definition of Base to take the handle type as a second parameter to avoid the circular dependency.
struct WidgetHandle {};
template <typename TWrapper, typename HandleType>
class Base
{
public:
typedef HandleType value_type;
Base(HandleType value_)
: value(value_) {}
HandleType value;
};
class Widget : public Base<Widget, WidgetHandle>
{
public:
Widget(WidgetHandle value_) : Base(value_) {}
};
int main(int argc, char* argv[])
{
Widget i(WidgetHandle());
return 0;
}
You could also use a traits class to get the WidgeHandle type for Widget.
struct WidgetHandle {};
class Widget;
template<class T>
struct Handle
{
};
template<>
struct Handle<Widget>
{
typedef WidgetHandle type;
};
template <typename TWrapper, typename HandleType = Handle<TWrapper>::type>
class Base
{
public:
typedef HandleType value_type;
Base(HandleType value_)
: value(value_) {}
HandleType value;
};
class Widget : public Base<Widget>
{
public:
Widget(WidgetHandle value_) : Base(value_) {}
};
int main(int argc, char* argv[])
{
Widget i(WidgetHandle());
return 0;
}
Related Topics
Is There a Standard Date/Time Class in C++
Best Practices for Recovering from a Segmentation Fault
Lambdas and Capture by Reference Local Variables:Accessing After the Scope
Ifstream Not Reading Eof Character
What Are the Operations Supported by Raw Pointer and Function Pointer in C/C++
In C++ 11, How to Invoke an Arbitrary Callable Object
How to Remove Straight Lines or Non-Curvical Lines in a Canny Image
For Loop Prints an Extra Comma
What Does -Fpic Mean When Building a Shared Library
How to Tell Reliably If a Boost Thread Has Exited Its Run Method
Legality of Using Operator Delete on a Pointer Obtained from Placement New
Piping (Or Command Chaining) with Qprocess
Qt Moc with Implementations Inside of Header Files
Are Variadic MACros Nonstandard
Qt MACro Keywords Cause Name Collisions