I.e. I got 2 specialized types of:
template <class Type, class Base> struct Instruction {};
to compile-time-select the appropriate type from within a type list.
like:
template <class Base> struct Instruction<Int2Type<Add_Type>, Base >
{
void add() {}
};
template <class Base> struct Instruction<Int2Type<Mul_Type>, Base > :
Instruction<Int2Type<Add_Type>, Base >
{
void mul()
{
add(); ???? <== not working (not resolved)
}
};
What's the solution for this?
Thank you
Martin
add() doesn't appear to depend on any template parameters (it's not a "dependent name"), so the compiler doesn't search for it in the templated base class.
One way to make it clear to the compiler that add() is supposed to be a member function/dependent name, is to explicitly specify this-> when you use the function:
void mul()
{
this->add();
}
this implicitly depends on the template parameters, which makes add a dependent name that is looked up in the templated base class.
See also this entry of the C++ FAQ lite, and the next/previous ones.
Got it using a "using base method" clause like:
using base::add;
One disadvantage is to declare that using clauses for all base methods. On advantage is the implicit distinctive nature of it selecting only that methods, which are allowed to resolve (use).
Sorry for that question of a dude which forgets his head somewhere.
Related
There are two classes:
class A {
public:
virtual void foo( int bar );
}
class B {
virtual void foo( string bar, int baz);
}
Now, the class(es) I'm building can derive from either class. But there's some common helper code, so I want to factor it out into a base class.
This common code must be called from foo and should take same arguments as the corresponding foo method. So I declare this template class, but don't know, whether it is possible to "extract" foo's signature from the template argument (which is a base class -- either A or B):
template<class Base>
class CommonBase : public Base {
public:
// how do I overload Base::foo here?
void foo(/*Base::foo arguments here*/) {
commonCode(/*Base::foo arguments here*/);
}
protected:
// how do I define commonCode with Base::foo signature below?
void commonCode(/*Base::foo arguments here*/) { ... }
}
I have little experience with C++ templates, so wondering -- is it even possible?
One solution I see is to add another template parameter for method signature and pass it explicitly when specializing. But it feels redundant as the knowledge of foo signature will be already contained in the Base class parameter (and compilation should fail if Base does not provide foo at all).
One solution I see is to add another template parameter for method signature and pass it explicitly when specializing.
This is on the right track, but you don't have to pass it explicitly; you can extract the type from the base class:
template<class Base, class... Arg>
class CommonBaseImpl : public Base {
public:
// how do I overload Base::foo here?
void foo(Arg... arg) override {
commonCode(std::forward<Arg>(arg)...);
}
protected:
// how do I define commonCode with Base::foo signature below?
void commonCode(Arg... arg) { ... }
};
template <class Base, class Foo = decltype(&Base::foo)>
struct BaseSelector;
template <class Base, class... Arg>
struct BaseSelector<Base, void (Base::*)(Arg...)>
{
using type = CommonBaseImpl<Base, Arg...>;
};
template <class Base>
using CommonBase = typename BaseSelector<Base>::type;
[Live example]
This works by using class template partial specialisation to decompose the function type. The template parameter Foo of BaseSelector will hold the type of member pointer to foo. To get this type, we use decltype(&Base::foo), the default argument for that parameter.
However, we need to access the individual argument types from within that type. This is normally done using template partial specialisation, as here. Basically, the primary template says: "This class template takes two types, Base and Foo." They're types and we know nothing more about them. We also don't use them for anything (the primary template is not even defined).
Then, we provide a specialisation. That effectively says: "When the type Foo happens to be a pointer to member function of Base which returns void and takes arguments of type Arg..., then do this: { partially specialised class definition }". In practice, it's just a way to assign names to the various components of the pointer-to-member type.
In page 668 of Stroustrup's book (4th edition - first printing) you`ll find the following example of a template class?
template<typename C>
class String{
public:
String();
...
private:
int sz;
C* ptr;
};
In page 679 the author writes:
Members of a template class are themselves templates parameterized by
the parameters of their template class. When such a member is defined
outside its class, it must explicitly be declared as template. For
example:
template<typename C>
String<C>::String()
:sz(0), ptr(ch)
{
ch[0] = {};
}
There is an obvious error in this example. The variable ch doesn't make any sense above. But that has nothing to do with my question. What I'd like to know is why the constructor above can't be defined without the parameter C, as shown below?
template<typename C>
String::String()
: sz(0), ptr(nullptr)
{
}
String is the name of a template, not a class. A template is not not even a type, so it doesn't have members. A template specialization is a class, however. You need to plug in C in order to specify which specialization it is you are referring to for the purposes of this definition.
Now it just so happens that the definition itself is a template, but that is because you are defining things for a family of specializations. Nevertheless the fact remains that you need to name those specializations explicitly.
Finally, the reason you only need to specify the specialization once is that the template name is treated in a special manner inside the scope of a class template specialization. Inside that scope the template name refers to the the injected class name, to the specialization itself. That's why
template<typename C>
String<C>::String<C>()
:sz(0), ptr(ch)
{
}
... can be written as...
template<typename C>
String<C>::String()
:sz(0), ptr(ch)
{
}
Since String<C> already established the specialization we are referring to, and we are inside its scope, we can use String with its special meaning as the injected class name.
C++ could have been designed with a special rule to make this trivial and common case work like you expect it to. The current rules are more consistent though, as they still work the in more complex cases.
In particular, consider the following :
template<typename C, int I> class String { };
template<typename C> class String<C,0> { String(); };
template<typename C> class String<C,1> { String(); };
This is a class template with two partial specializations.
Now the first ctor is defined as
template<typename C> String<C,0> :: String() { }
You see that the template argument list has one extra argument, ,0 which indicates the specific specialization. Partial specializations vary some, but not all template parameters of the base template. You have to specify which parameters can vary, and which have fixed values.
I have an inheritance chain of CRTP classes. The CRTP classes derive from each other, until a 'final' derived class passes itself as the CRTP parameter and finalizes the inheritance chain.
template <class W>
struct Base
{
.....
};
template <class W>
struct Derived_inheritable: public Base<W>
{
....
}
template <class W>
struct Derived2_inheritable: public Derived_inheritable<W>
{
....
}
...
What I want to do is to be able to have such 'final' end-user classes at each level of the CRTP inheritance chain, that involve no templates:
typedef Derived1_inheritable<Derived1> Derived1;
As you can guess, this typedef does not work, because it references its own type being defined. The question is how to achieve this?
The way I could think of, is:
struct Derived1: public Derived1_inheritable<Derived1>
{
//not convenient, need to redefine at least a forwarding constructor
}
As the comment in the code says, this is not a very elegant solution - I need to redefine the constructor to forward to the base constructor. Does anyone know a more elegant way?
typedef Derived1_inheritable Derived1;
That line makes no sense, the argument to the template is a type but you are trying to pass a template (incidentally the same template that you are instantiating, but besides that extra quirk the fact is that your template takes a type as argument and you are passing a non-type)
It is not really clear from the question what you are trying to achieve. You should work on stating your goal rather than your approach to solving that goal.
I want to make a "final" class for each DerivedX_inheritable that is non-template and passes itself as the W parameter.
That is exactly done in the code that you produded:
struct Derived1: public Derived1_inheritable<Derived1> {}
which is a type definition (make a "final" class). The fact that your CRTP bases require arguments that must be provided by the end user and the need of the forwarding constructor thereof is just a side effect of your design.
I think I found an elegant solution:
template <class W>
struct Base
{
.....
};
template <class W>
struct Derived_inheritable: public Base<W>
{
....
}
//solution
struct Derived2_dummy;
template <class W=derived2d_ummy>
struct Derived2_inheritable: public Derived_inheritable<W>
{
....
}
struct derived2_dummy: public: Derived_inheritable<>{};
typedef Derived2_inheritable<> Derived2;
I was wondering if there could be any way to write a template function in an abstract class, and have it (the template function) automatically instantiated with the type of the derived class?
So you have a class that looks something like this
class A
{
virtual template < typename T>
void vtfunc(void)
};
class B : public A
{
/// No declared members pertaining to this example
}
Then, whenever a class derived from A is declared, it compiles "vtfunc" with itself as the template parameter T.
Then, calling vtfunc() through an interface of A calls the isntance of that function compiled for its derived class B.
Is there any way of doing this, or writing something fiddley that have this effect?
Obviously I am aware that the template parameter could only affect the internals of the class, and not the return type and parameters - they would need to be the same because of the way polymorphism works.
I’m not sure what you’re after but one common pattern is the so-called curiously recurring template pattern; here, the base class itself is the template, not its member functions. In other words:
template <typename T>
class A
{
virtual void vtfunc(void)
};
class B : public A<B>
{
…
};
Consider using a non-member function instead.
In this piece I'm trying to declare in Class B a list that can hold objects of Class A of any type, such as A<int>, A<double>, A<float>. I intend to add A objects to the list during runtime:
#include <list>
template <class T> class A {};
class B {
template<class T> std::list<A<T>*> objects;
};
It seems like making a list like this should work but compiling it gives an error:
Line 6: error: data member 'objects' cannot be a member template
compilation terminated due to -Wfatal-errors.
Can somebody explain why this doesn't work and how I can fix it?
That's just not how C++ works. If you want to group different objects together, they need to have at least some relation. Being instantiations of the same class template doesn't imply that they are related, they're completely distinct types. If you want a list of A<T>*s, better make a list of base-class pointers and forward operations through virtual functions:
class A_base{
public:
virtual void foo() = 0;
virtual ~A_base() { }
};
template<class T>
class A : public A_base{
public:
void foo(){
// ...
}
};
class B{
std::list<A_base*> objects;
};
Member variables aren't allowed to be templates. Only member functions can be templates. You'll have to templatize the enclosing class B instead:
template <class T>
class B {
std::list<A<T>*> objects;
};
Unfortunately you cannot have template variables. Only option to declare a member data is to make the class template:
template<class T>
class B {
std::list<A<T>*> objects;
};
Depending on what you're doing, type erasure might be an option. On the Tension Between Object-Oriented and Generic Programming in C++ is my favorite write-up on the subject.
In a nutshell, you convert the static dispatch enabled by the templates into dynamic dispatch through a custom inheritance tree you setup on the fly. Instead of storing A<T>, you create a new type that has the common interface you desire, and using some template/inhertiance voodoo this new type stores an A<T> without actually exposing the T. So A<int> and A<double> and A<A<std::list<A<int> > > > and some_type_that_looks_like_A_but_really_isnt all reduce down to a single type.
But you have to have a common interface, independant of that parameter. If you can't, things get more difficult.
Boost.Any is a good example, as is std::shared_ptr [which uses type erasure to remember how to delete the pointer passed to it even in the face of non-polymorphic inheritance].
Make B class template just like you've made A a class template:
template<class T>
class B {
std::list<A<T>*> objects;
};