class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name>
{
public:
MyDerived();
}
MyDerived::MyDerived
: ???(params)
{}
Is there any way to call a base constructor without writing its full name and without typedeffing it?
The reason is clearly to avoid code duplication and introducing multiple positions to change if a detail in the base class template params changes.
Level 2 of this:
template <uint32 C>
class MyDerived: public Incredble<Difficult< And<Complicated, Long>>, And<Even, Longer>, BaseClass, Name>
{
public:
MyDerived();
}
template <uint32 C>
MyDerived::MyDerived<C>
: ???(C)
{
}
You could use injected-class-name. Incredible<...>::Incredible refers to itself, and since MyDerived isn't a class template, unqualified lookup will look in the scope of its base classes:
MyDerived::MyDerived
: Incredble(params)
{}
If Incredible is a dependent name, then you need to qualify it. You can actually simply use the derived type name to qualify the base class's injected-class-name (h/t Johannes Schaub-litb):
MyDerived::MyDerived
: MyDerived::Incredible(params)
{}
This will work in all cases.
If you don't wont to use using or typedef to avoid "polluting the enclosing namespace", you can use using inside the class/struct.
An example
#include <map>
template <typename ...>
class foo
{};
struct A : public foo<int, std::tuple<long, char, std::map<std::string, int>>>
{
using base_t = foo<int, std::tuple<long, char, std::map<std::string, int>>>;
A () : base_t{}
{ };
};
int main()
{ }
Related
I have some code like this:
#include <string>
#include <map>
typedef std::less<std::string> Comparator; // simplified
typedef std::allocator<std::pair<const std::string, int>> Allocator; // simplified
template<class T>
struct Base
{
typedef std::map<std::string, T, Comparator, Allocator> type; // VERY long declaration in the actual code
};
template<class T>
struct Container : public Base<T>::type
{
Container(Allocator a) : Base<T>::type(Comparator(), a) {}
};
int main()
{
Allocator a;
Container<int> c(a);
}
Although the declarations are a bit more fancy in my actual code.
The Base struct is used so that I do not have to write the long map declaration multiple times.
I was wondering if there is a better way to inherit from the map without any Base struct?
No macros please. I hope in some way to hide the typedef in the Container class itself or something like that.
Thanks,
You can rely on templates having an injected class name. Inside the specialization of map<...>, the current specialization can be referred to simply by map. And that injected class name is also available to derived classes (and class templates). But since it's dependent, it requires a qualified name. It looks simpler than it sounds, here's how you roll the alias into Conatiner:
template<class T>
struct Container : public std::map<std::string, T, Comparator, Allocator>
{
using Base = typename Container::map;
Container(Allocator a) : Base(Comparator(), a) {}
};
Container::map is the injected class name. And the alias grabs it for convenient use.
I have some code like this
class A : public b<T>
{
public:
typedef b<T> _baseclass; // why we need this declaration
};
What is the use of typedef inside the class?
Is the definition limited to this class only?
Shall we create this as static and use without crating an object of the class?
This member type will be available outside of the class definition too, which is convenient in template code. If you passed an A into a function template, or maybe some other classes that also have _baseclass member types, then you can use _baseclass to find out what the base is without needing to know exactly what the top-level type is.
Standard templates like std::vector and std::map have member types like value_type — these do not signify a base class but have a similar purpose, in that you can use value_type anywhere a container is used, no matter which container is used.
Swapping typedef to using (because I want to), here's an example:
// The class templates
template <typename T>
struct Base {};
struct A : Base<int>
{
using base_class = Base<int>;
};
struct B : Base<char>
{
using base_class = Base<char>;
};
struct C : Base<bool>
{
using base_class = Base<bool>;
};
// The example
template <typename T>
void foo()
{
// typename needed because base_class is a "dependent name"
// (just go with it)
typename T::base_class the_base;
// This line is to suppress "unused variable" warnings
(void)the_base;
}
int main()
{
foo<A>();
foo<B>();
foo<C>();
}
Though this particular program doesn't actually "do anything", it shows a function template foo that can "know" what the base class was in each case, without any further information about exactly what T is. And it'll work for any class to which you've added a base_class member type!
Given a base class using CRTP, I'm looking at declaring a member in the base template class where the type is dependent of the derived class.
While the following works as intended:
template <class T> class BaseTraits;
template <class T> class Base {
using TypeId = typename BaseTraits<T>::TypeId;
TypeId id;
public:
Base() { id = 123; }
TypeId getId() { return id; }
};
class Derived;
template <> class BaseTraits<Derived> {
public:
using TypeId = int;
};
class Derived : public Base<Derived> {};
int main(int argc, char ** argv) {
Derived foo;
return foo.getId();
}
I wonder if I could simplify the implementation. I could add a second template parameter to the Base template, and make BaseTraits simpler or even get rid of it. However the above snippet is already an attempt to remove the second template parameter. I'm looking at solutions that doesn't involve a second template parameter for Base.
I've tried something like the following but it doesn't compile:
error: invalid use of incomplete type 'class Derived'
template <class T> class Base {
using TypeId = typename T::TypeId;
TypeId id;
public:
Base() { id = 123; }
TypeId getId() { return id; }
};
class Derived : public Base<Derived> {
public:
using TypeId = int;
};
int main(int argc, char ** argv) {
Derived foo;
return foo.getId();
}
UPDATE:
I'm limited to c++14.
Base must be a template.
Performance is a must.
Is it possible to make a member type directly dependent on the derived class? Taking appart the result type of a member function declared with auto (deduced return type), it is not possible.
So the use of a type-trait as you do in your solution is the best and only solution.
The reason is that a base class must be a complete type when the derived class is defined: the compiler must first instantiate and parse the base class definition before it parses the derived class definition, C++ standard N4140 [derived.class]/2 (bold is mine):
The type denoted by a base-type-specifier shall be a class type that is not an incompletely defined class;[...]
What about something like this:
template <typename T, typename TypeId> class Base
{
private:
TypeId id;
public:
Base() { id = 123; }
TypeId getId() {return id;}
};
class Derived : public Base<Derived, int> {};
This is kind of simplified, but you pay some price for it.
#include <any>
template <class T> class Base {
std::any id; // expensive, but cannot have T::TypeId here
public:
Base() : id(123) {}
auto getId() {
return std::any_cast<typename T::TypeId>(id);
} // T::TypeId is OK inside a member function
};
class Derived : public Base<Derived> {
public:
using TypeId = int;
};
Why not reversing the class hierarchy?
template <class T>
class Base : T {
using TypeId = typename T::TypeId;
TypeId id;
public:
Base() { id = 123; }
TypeId getId() { return id; }
};
struct BasicDerived {
using TypeId = int;
};
using Derived = Base<BasicDerived>;
Actually, I thought some more... this isn't too unpleasant:
You could have a binding struct, could even be written as a macro, declared just before the real class.
The binding struct defines the enum and an incomplete typedef to the real class.
The template is defined before all of that, but uses typename to defer its dependency, but it is instanced by the real class and only dependant on the binding struct
template <class ThatClassWrapper>
class MyBase
{
protected:
typedef typename ThatClassWrapper::TypeId TypeId;
typedef typename ThatClassWrapper::RealClass ThatClass;
TypeId typeIdValue;
TypeId GetTypeId() { return typeIdValue; }
std::vector<ThatClass*> storage;
};
class SomeClass;
namespace TypeIdBinding
{
struct SomeClass
{
enum TypeId
{
hello, world
};
typedef ::SomeClass RealClass;
};
}
class SomeClass: public MyBase<TypeIdBinding::SomeClass>
{
public:
bool CheckValue(TypeId id)
{ return id == typeIdValue; }
};
Note that the real class is using TypeId as defined in the template base, and the named members are not directly visible. You could fix that by having the template Base derive from the binding struct (confirmed that it compiles that way). though I actually like that in c++11 you can export or typedef just the enum typename from another namespace and use that type name as a prefix for the enum members, helping to avoid name pollution.
To be honest you have hit the wall of hard circular dependencies.
Any way out will be smelly.
Two template arguments seems like a small price in the end.
Could you declare a dummy template class that takes Derived and TypeID? I don't think it gains you anything, though.
Is TypeID:Derived a 1:1 mapping? Would it feel better to over-represent that 1:1 mapping with another helper template to back-look-up Derived from TypeID? Note that TypeID would need to be defined outside the Derived class to do this.
Does TypeID really need to be defined inside the class? Could it leach off the passed-in definition in Base to support the existing use of the internal typedef?
Can you double-include? Split or macriose your definition of derived so that typeid is in a base class definition that can be included before the template? This DerivedBase could be declared in a namespace and contain a typedef link back to the full Derived class so Base can find it for references.
Hi I am not sure that this is possible since but I thought of asking since there might be better ways of achieving something similar that I am not aware of.
For simplicity lets just consider that VectorT is
template<class T>
class VectorT: private std::vector<T>`
An attempt to what I wanted to have is something along the lines of.
namespace detail
{
template<class SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr>
{
public:
MyClassVectorBase() = default;
// all common functions of MyVectorView and MyVector
};
}
using MyClassVectorView = detail::MyClassVectorBase<nonstd::observer_ptr<SomeClass>>;
class MyVector : public detail::MyClassVectorBase<std::unique_ptr<SomeClass>>
{
// only functions related to the actual owner vector
};
What I am hoping is that MyClassVectorBase can be templated only on the smart pointer type and only accept SomeClass.
I thought that it might be possible with a specialization but I got no idea what the syntax for something like that would be
template<class T, class SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr<T>>
{
};
template<SomeClass T, typename SmartPtr>
class MyClassVectorBase : public VectorT<SmartPtr<T>>
{
};
Is something like that even possible ?
Edited:
Ok let me try to explain this and the logic behind it. I need to have a VectorT of Foo objects. Only Foo and nothing else.
In one case the class will be the owner of the objects and have a few extra functions.
Since it is the owner it will be class MyClassVector : public VectorT<std::unique_ptr<Foo>>
Then I have to somehow operate on these objects but these wont be owned.
The ownership is single and will always outlive the object that I will operate on so no need for shared_ptr.
So Then I guess my class will be a "View class" MyClassVectorView : public VectorT<std::observer_ptr<Foo>>
Instead of observer_ptr it could as well be say raw ptr but the intent is better with it.
Now MyClassVectorView will have all identical functions with MyClassVector which is why I think that I would be inheriting from it.
To do so I need to have a base class that will accept both unique_ptr and observer_ptr.
Then I can avoid duplication so long as I can do MyClassVector : public MyClassVectorView<std::unique_ptr<Foo>>
The alterantive would be have one class and detect with SFINAE if the template parameter is a unique_ptr and then enable the extra functions. This would avoid the extra inheritance.
Not sure about what you want to obtain but I suspect that you need template template parameters.
I suppose you could declare (but not define) MyClassVectorBase as receiving a single template typename parameter
template <typename>
class MyClassVectorBase;
and next define a specialization template-template based; something like
template <template<typename...> class SmartPtr, typename Foo>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
If Foo isn't a template parameter, but is the Foo struct, you can write
template <template<typename...> class SmartPtr>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
Your example modified and integrated (with a main() and a dummy observer_ptr)
#include <iostream>
#include <string>
#include <vector>
#include <memory>
namespace nonstd
{
template <typename T>
struct observer_ptr
{ };
}
template <class T>
class VectorT
{
public:
// expose nececssary functions
private :
std::vector<T> container_;
};
struct Foo{
double x;
};
template <typename>
class MyClassVectorBase;
// this class should only accept smart pointers of Foo
template <template<typename...> class SmartPtr, typename Foo>
class MyClassVectorBase<SmartPtr<Foo>> : public VectorT<SmartPtr<Foo>>
{
public:
MyClassVectorBase() = default;
void doSomething(){}
void doSomething2(){}
};
using MyClassVectorView = MyClassVectorBase<nonstd::observer_ptr<Foo>>;
class MyVector : public MyClassVectorBase<std::unique_ptr<Foo>>
{
// function only for this class but still inheriting all MyClassVectorBase stuff
};
int main ()
{
}
I'm trying to implement a kind of CRTP (if I well understand what it is) with multiple inheritance.
My main goal is to have a unified way to access list of instances of each subclass.
May problem seems to reside in the namespace utilization.
Here is the code of the simplest version :
http://ideone.com/rFab5
My real problem is more similar to :
http://ideone.com/U7cAf
I have an additional warning using clang++ :
test.cpp:28:63: warning: static data member specialization of 'instances' must originally be declared in namespace 'NS1'; accepted as a C++0x extension [-Wc++0x-extensions]
template <> std::list<NS1::Derived*> NS1::Base<NS1::Derived>::instances;
^
test.cpp:15:34: note: explicitly specialized declaration is here
static std::list<T*> instances;
Problem has been updated since it does not behave the same using namespaces.
Problem re-edited to post code on Ideone
The problem is that you've tried to define the list variable wrong. You need to provide a definition for Base, in general- you don't just define it for the one part that happens to be Derived's subclass, unless it's an explicit specialization.
template<typename T> std::list<T*> NS1::Base<T>::instances;
http://ideone.com/Vclac
Compiles with no errors. There are no intermediates or anything like that required.
Changing Base() and Intermediary() to Base<U>() and Intermediary<Derived> in the constructors makes the code OK for GCC.
There is no reason to change the definition of instances in the second case: the template is identical as the first situation.
Afaik, you got the following options.
First, if Intermediate is always templated on the derived type, you don't need a list for it, because it will never be the most derived type. If it could be templated on other types / not be derived, you can add a defaulted non-type bool template parameter like so:
template<bool, class A, class B>
struct select_base{
typedef A type;
};
template<class A, class B>
struct select_base<false,A,B>{
typedef B type;
};
template<class T, bool IsDerived = false>
class Intermediate
: public select_base<IsDerived,
Base<T>,
Base<Intermediate<T> >
>::type
{
// ...
};
// derived use
class Derived : public Intermediate<Derived, true>
{
// ...
};
// non-derived use:
Intermediate<int> im;
If the intermediate class is not templated and does not already derive from Base, you need to derive from Base again in the most derived class:
class Derived : public Intermediate, public Base<Derived>
{
// ...
};
The big problem comes when the intermediate also derives from Base but is not templated. You can add a defaulted derived type, but that would make the non-derived use a bit more ugly:
#include <type_traits> // C++0x, use std::
//#include <tr1/type_traits> // C++03, use std::tr1::
struct nil_base{};
template<class Derived = nil_base>
class Intermediate
: public select_base<std::is_same<Derived,nil_base>::value,
Base<Intermediate<Derived> >, //
Base<Derived>
>::type
{
// ...
};
// derived use now without boolean flag
class Derived : public Intermediate<Derived>
{
// ...
};
// non-derived use a bit uglier
Intermediate<> im;
// ^^ -- sadly needed
The following compiles OK with MinGW g++ 4.4.1, MSVC 10.0, and Comeau Online 4.3.10.1:
#include <list>
template <class T>
class Base
{
protected:
Base()
{
instances.push_back(static_cast<T*>(this));
}
private:
static std::list<T*> instances;
};
template <class U>
class Intermediary : public Base<U>
{
protected:
Intermediary()
:Base<U>()
{
}
};
class Derived : public Intermediary<Derived>
{
public:
Derived()
:Intermediary<Derived>()
{
}
};
template<class Derived> std::list<Derived*> Base<Derived>::instances;
int main()
{}
The instances definition is copied verbatim from your question.
I say as Isaac Newton, I frame no hypotheses!
Cheers & hth.,