I want to create a template container-class that should store instances
of ABC
-derived classes. With a constraint that only ABC
-derived classes can use this template.
The container should be a static member of the derived class.
This is what I have now, though this won't work since extendsABC
is not expecting a shared_ptr
:
#include <list>
#include <memory>
#include <type_traits>
class ABC {
virtual void foo() = 0;
};
template <typename T>
concept extendsABC = std::is_base_of<ABC, T>::value;
template <extendsABC T>
struct extendsABCStore {
std::list<T> m_data;
};
struct Derived;
struct Derived : public ABC {
void foo() override{};
static extendsABCStore<std::shared_ptr<Derived>> instances;
};
<source>:22:10: error: constraints not satisfied for class template 'extendsABCStore' [with T = std::shared_ptr<Derived>]
static extendsABCStore < std::shared_ptr < Derived >> instances;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:13:12: note: because 'std::shared_ptr<Derived>' does not satisfy 'extendsABC'
template < extendsABC T >
^
<source>:11:24: note: because 'std::is_base_of<ABC, shared_ptr<Derived> >::value' evaluated to false
concept extendsABC = std::is_base_of<ABC, T>::value;
^
1 error generated.
Compiler returned: 1
You have a couple of problems. Within the definition of Derived
, it is an incomplete type, so extendsABC<Derived>
is false
. You also have a pointer where you want to constrain on the pointed-to type.
To fix the first, we can use a static member function rather than a static data member.
struct Derived : public ABC {
void foo() override{};
static auto& instances() {
static extendsABCStore<Derived> store;
return store;
}
};
To fix the second, put std::shared_ptr
in the definition of extendsABCStore
template <typename T>
struct extendsABCStore {
std::list<std::shared_ptr<T>> m_data;
};