Trick to explicit choose overloaded method without static_cast - c++

This is a question mainly about making the code easier on the eyes.
I have a template class t<T, Ts...> that generates an overloaded method, overloaded_method(x<T> *), for each template argument T. The argument on this method is not of the template argument type directly but for some other specialization template class, x<T>.
So, given class a and class b, we have t<a,b> which has overloaded_method(x<a> *) and overloaded_method(x<b> *).
After that I create an implementation class impl that implements x<a> and x<b>.
If I try to call overloaded_method() with an object ii of impl, the compiler doesn't know if it has to choose overloaded_method(x<a> *) or overloaded_method(x<b> *), which is understandable.
I can help the compiler by using static_cast. Eg. ti.overloaded_method(static_cast<x<a> *>(&ii)).
This works fine, but feels like a thorn in the eye, and wouldn't be nice for a user of my library. I would rather do something like ti.overloaded_method<a>(&ii), which is invalid.
Is there any way to explicitly choose which overloaded method to use, that doesn't involve static_cast and x?
template<typename T>
class x {
public:
T *v;
};
template<typename...>
class t {
public:
void overloaded_method();
};
template <typename T, typename... Ts>
class t<T, Ts...>: public t<Ts...> {
public:
void overloaded_method(x<T> *v) {
}
using t<Ts...>::overloaded_method;
};
class a
{
};
class b {
};
class impl: public x<a>,
public x<b> {
};
int
main (int argc, char *argv[])
{
t<a, b> ti;
impl ii;
ti.overloaded_method(static_cast<x<b> *>(&ii));
return 0;
}

Related

How to limit template parameters to a descendent that is a specialization of a templated interface?

Assume the following situation:
There is a templated interface defining a set of operations on different data types.
This interface is implemented by various specialized classes defining the operations for actual data types.
There is some managing class that has to work instances of classes as defined in 2.
Simplified example code could look like this:
#include <iostream>
#include <type_traits>
template <typename R, typename S>
class ICanDoIt
{
public:
virtual void doStuff() = 0;
protected:
ICanDoIt<R, S>(R rA, S sA) : r(rA), s(sA) {};
R r;
S s;
};
class DoesIt : public ICanDoIt<int, double>
{
public:
DoesIt(int iA, double dA) : ICanDoIt(iA, dA) {};
virtual void doStuff()
{ std::cout << "r * s = " << r * s << " done." << std::endl; }
};
template <typename T>
class NeedsSomeoneWhoCanDoIt
{
static_assert(std::is_base_of<ICanDoIt<R, S>, T>::value,
"T needs to be able to do it.");
public:
NeedsSomeoneWhoCanDoIt(const T& doesItA) : doesIt(doesItA) {};
void getItDone() { doesIt.doStuff(); };
private:
T doesIt;
};
int main()
{
DoesIt doesIt(5, 2.2);
NeedsSomeoneWhoCanDoIt<DoesIt> needsIt(doesIt);
needsIt.getItDone();
}
If you untemplate the interface "ICanDoIt" the code will actually work. But the static_assert for the templated version will fail because ICanDoIt's template arguments are wrapped and hidden by the specialization performed in the decalaration of DoesIt.
How can I limit the managing classes (NeedsSomeoneWhoCanDoIt) template parameter "T" to any specialization of ICanDoIt, regardless of which type has been chosen for R, S during the specialization of ICanDoIt?
You could always make the actual types for R and S used to instantiate ICanDoIt accessible to a derived class, i.e.
template <typename R, typename S> class ICanDoIt {
public:
typedef R R_t;
typedef S S_t;
virtual void doStuff() = 0;
};
so that your static_assert would become
static_assert(std::is_base_of<ICanDoIt<typename T::R_t, typename T::S_t>,
T>::value,
"T needs to be able to do it.");
Depending on what your actual code looks like the design might become clearer if you'd define a purely abstract base class (i.e. an actual type ICanDoItBase instead of a template) from which you'd inherit the currently templated functionality in ICanDoIt which would again be a base of DoesIt.
NeedsSomeoneWhoCanDoIt could then directly use the the polymorphic base class ICanDoItBase without any needs for additional type checks.
You don't need to publish the template parameters. The standard SFINAE-based approach would work just fine.
namespace detail {
template<class R, class S>
std::true_type test(ICanDoIt<R, S>*);
std::false_type test(...);
}
template<class T>
using can_do_it = decltype(detail::test((T*)nullptr));

Templated Member Function of Templated Class

I have a templated C++ class which has a templated member function as well. The template parameters of this member function are dependent on the class's template parameters in a specific way (please see the code below).
I am instantiating (not specializing) this class for two different values of its template parameter. Everything compiles till this point. However, if I invoke the templated member function, the call for only the first instantiated object compiles and not the second one.
It appears as if the compiler is not instantiating the templated member function for the second instantiation of the template class. I am compiling the code below using "g++ filename.cpp" and am getting the following error:
filename.cpp:63: error: no matching function for call to 'Manager<(Base)1u>::init(Combination<(Base)1u, (Dependent2)0u>*)’
This is the line calling b.init(&combination_2)
g++ --version => g++ (Ubuntu/Linaro 4.4.7-1ubuntu2) 4.4.7
uname -a => Linux 3.2.0-25-generic-pae #40-Ubuntu SMP i686 i686 i386 GNU/Linux
enum Base {
AA,
BB,
CC
};
enum Dependent1 {
PP,
QQ,
RR
};
enum Dependent2 {
XX,
YY,
ZZ
};
template<Base B>
struct DependentProperty {
};
template<>
struct DependentProperty<AA> {
typedef Dependent1 Dependent;
};
template<>
struct DependentProperty<BB> {
typedef Dependent2 Dependent;
};
template <Base B, typename DependentProperty<B>::Dependent D>
class Combination {
public:
void reset() {}
int o;
};
template <Base B>
class Manager {
public:
template <typename DependentProperty<B>::Dependent D,
template<Base,
typename DependentProperty<B>::Dependent> class T>
void init(T<B, D>* t);
};
template <Base B>
template <typename DependentProperty<B>::Dependent D,
template<Base,
typename DependentProperty<B>::Dependent> class T>
void Manager<B>::init(T<B, D>* t) {
t->reset();
}
int main(int argc, char** argv) {
Manager<AA> a;
Manager<BB> b;
Combination<AA, PP> combination_1;
Combination<BB, XX> combination_2;
a.init(&combination_1);
b.init(&combination_2);
return 0;
}
It is not feasible to modify the classes corresponding to Base, Dependent or Combination from my example code in our actual project. What I am really wondering is whether my syntax for defining Manager::init() is wrong, or whether there is some known property/feature/constraint of C++ or g++ that wouldn't allow this code?
The code below compiles for me, I have simplified your code a little, though it still does the same thing.
template <Base B>
class Manager {
public:
typedef typename DependentProperty<B>::Dependent D; // if ever you need it
template <typename TCombinaison>
void init(TCombinaison* t)
{
t->reset();
}
};
int main(int argc, char** argv)
{
typedef Combination<AA, PP> CombinaisonA;
typedef Combination<BB, XX> CombinaisonB;
typedef DependentProperty<AA> DependencyPropertyA;
typedef DependentProperty<BB> DependencyPropertyB;
CombinaisonA combination_1;
CombinaisonB combination_2;
Manager<AA> a;
Manager<BB> b;
a.init(&combination_1);
b.init<&combination_2);
return 0;
}
EDIT: A 2nd solution so as to forbid the mixed use of combination in managers, as the OP has noticed in the comments below. Now I'm using std::is_same to check the "concept" contract.
template <Base B, typename DependentProperty<B>::Dependent D>
class Combination {
public:
typedef typename DependentProperty<B>::Dependent DependencyType;
void reset() {}
int o;
};
template <Base B>
class Manager {
public:
typedef typename DependentProperty<B>::Dependent DependencyType;
template <typename TCombinaison>
void init(TCombinaison* t)
{
static_assert(std::is_same<TCombinaison::DependencyType, Manager::DependencyType>);
t->reset();
}
};
If you combine inheritance and go away from constant template parameters, extend the Combination to provide info on its template arguments, you can get the code to compile taking into account that you don't want this to compile:
b.init(&combination_1);
You are trying very hard to specify and fix the type of the Combination for the init member template within your Manager indirectly, even though the init template will deduce it since it is the only parameter of the function, and the type si defined within main anyway.
Would you consider templating the init directly with the Combination?
This way, everything apart from the init() declaration remains the same, and your code compiles as you wanted to initially:
class Base
{
};
class AA
:
public Base
{
};
class BB
:
public Base
{
};
class Dependent1
{
};
class PP
:
public Dependent1
{};
class Dependent2
{};
class XX
:
public Dependent2
{};
template<class Base>
struct DependentProperty {
};
template<>
struct DependentProperty<AA> {
typedef Dependent1 Dependent;
};
template<>
struct DependentProperty<BB> {
typedef Dependent2 Dependent;
};
template <class Base>
class Combination {
public:
typedef Base CombinationBase;
typedef typename DependentProperty<Base>::Dependent CombinationDependent;
void reset()
{
}
int o;
};
template <class Base>
class Manager
{
public:
// Any type C
template<class C>
void init (C* t)
{
// Any type C conforming to the implicit interface holding reset()
t->reset();
// Forcing specific combination
Base b = typename C::CombinationBase();
// Forcing it again
typename DependentProperty<Base>::Dependent d = typename C::CombinationDependent();
}
};
int main(int argc, char** argv) {
Combination<AA> combination_1;
Manager<AA> a;
a.init(&combination_1);
Manager<BB> b;
Combination<BB> combination_2;
b.init(&combination_2);
b.init(&combination_1);
return 0;
}
In this case, you can extend the Combination template to provide access to its template parameters to the client code. Of course the template C in this case becomes a refinement of the Combination concept as soon as you rely on its implementation within the init member function (accessing the stored template argument values, etc).
Your code is correct, except for the function calling part.
a.init<PP, Combination>( &combination_1 );
b.init<XX, Combination> ( &combination_2 );
This compiles and runs peacefully.
The only thing I see is
template <typename DependentProperty<B>::Dependent D,
template<Base, <-- wrong
typename DependentProperty<B>::Dependent <-- wrong
> class T>
void init(T<B, D>* t);
Your class Combination waits values as a template parameter, but you want to give him types
I spent some time to fix it - like that
template <typename DependentProperty<B>::Dependent D,
template<Base BB,
typename DependentProperty<BB>::Dependent DD
> class T>
void init(T<B, D>* t);
and many other variants, but had no success.
Excuse me for arrange it as an answer, but I couldn't type so many code in a comment

CRTP with Protected Derived Member

In the CRTP pattern, we run into problems if we want to keep the implementation function in the derived class as protected. We must either declare the base class as a friend of the derived class or use something like this (I have not tried the method on the linked article). Is there some other (simple) way that allows keeping the implementation function in the derived class as protected?
Edit: Here is a simple code example:
template<class D>
class C {
public:
void base_foo()
{
static_cast<D*>(this)->foo();
}
};
class D: public C<D> {
protected: //ERROR!
void foo() {
}
};
int main() {
D d;
d.base_foo();
return 0;
}
The above code gives error: ‘void D::foo()’ is protected with g++ 4.5.1 but compiles if protected is replaced by public.
It's not a problem at all and is solved with one line in derived class:
friend class Base< Derived >;
#include <iostream>
template< typename PDerived >
class TBase
{
public:
void Foo( void )
{
static_cast< PDerived* > ( this )->Bar();
}
};
class TDerived : public TBase< TDerived >
{
friend class TBase< TDerived > ;
protected:
void Bar( void )
{
std::cout << "in Bar" << std::endl;
}
};
int main( void )
{
TDerived lD;
lD.Foo();
return ( 0 );
}
As lapk recommended, problem can be solved with simple friend class declaration:
class D: public C<D> {
friend class C<D>; // friend class declaration
protected:
void foo() {
}
};
However, that exposes all protected/private members of derived class and requires custom code for each derived class declaration.
The following solution is based on the linked article:
template<class D>
class C {
public:
void base_foo() { Accessor::base_foo(derived()); }
int base_bar() { return Accessor::base_bar(derived()); }
private:
D& derived() { return *(D*)this; }
// accessor functions for protected functions in derived class
struct Accessor : D
{
static void base_foo(D& derived) {
void (D::*fn)() = &Accessor::foo;
(derived.*fn)();
}
static int base_bar(D& derived) {
int (D::*fn)() = &Accessor::bar;
return (derived.*fn)();
}
};
};
class D : public C<D> {
protected: // Success!
void foo() {}
int bar() { return 42; }
};
int main(int argc, char *argv[])
{
D d;
d.base_foo();
int n = d.base_bar();
return 0;
}
PS: If you don't trust your compiler to optimize away the references, you can replace the derived() function with the following #define (resulted in 20% fewer lines of disassembly code using MSVC 2013):
int base_bar() { return Accessor::base_bar(_instance_ref); }
private:
#define _instance_ref *static_cast<D*>(this) //D& derived() { return *(D*)this; }
After some I came with a solution that works event for private members of templated derived classes. It does not solves the problem of not exposing all the members of the derived class to the base, since it uses a friend declaration on the whole class. On the other hand, for the simple case, this does not requires repeating the base name, nor it's template parameters and will always work.
First the simple case when the derived is non-template. The base takes an additional void template parameter just to show that everything still works in the case of extra template parameters of the base. The only needed one, as per the CRTP, is the typename Derived.
//Templated variadic base
template <typename Derived, typename...>
struct Interface
{
using CRTP = Interface; //Magic!
void f() { static_cast<Derived*>(this)->f(); }
};
//Simple usage of the base with extra types
//This can only be used when the derived is NON templated
class A : public Interface<A, void>
{
friend CRTP;
void f() {}
};
The only thing needed for this to work is the using CRTP = Interface; declaration in the base and the friend CRTP; declaration in the derived.
For the case when the derived is itself templated the situation is trickier. It took me some time to come to the solution, and I'm sure it's still not perfect.
Most of the magic happens inside these templates:
namespace CRTP
{
template <template <typename, typename...> class _Base, typename _Derived, typename... _BaseArgs>
struct Friend { using Base = _Base<_Derived, _BaseArgs...>; };
template <template <typename, typename...> class _Base, typename ..._BaseArgs>
struct Base
{
template <template <typename...> class _Derived, typename... _DerivedArgs>
struct Derived : public _Base<_Derived<_DerivedArgs...>, _BaseArgs...> {};
};
}
Their usage is more or less straightforward. Two use the above templates several steps are needed.
First, when inheriting in the derived class the inherited-from base class, and it's optional parameters, needs to be given. This is done using CRTP::Base<MyBase, BaseOptional....>, where MyBase is the name of the class used for CRTP, and the BaseOptional... are template parameters that are passed to the base class as-is, directly after passing our derived class that is supplied in the next step. When the base class does not accepts any additional template parameters they can be omitted completely: CRTP::Base<MyBase>.
The next step is to introduce the derived class (the whole point of CRTP). This is done by following the above CRTP::Base<...> with a ::Derived<ThisDerived, DerivedOptional...>. Where ThisDerived is the class this is defined in, and DerivedOptional... are all the template parameters declared in this class'es template declaration. The optional parameters much be specified exactly as they appear in the class template declaration.
The last step is declaring the base class as a friend. This is done by declaring friend typename CRTP::Friend<MyBase, ThisDerived, BaseOptional...>::Base somewhere in the class. The BaseOptional... template perameters must be repeated exactly as they appear in the CRTP::Base<MyBase, BaseOptional...> that is inherited from.
Follows is an example of using a templated derived when the base does not depends on the templated types (but it still can take other template parameters, void in this example).
//Templated derived with extra, non-dependant types, passed to the base
//The arguments passed to CRTP::Base::Derived<, ARGS> must exactly match
// the template
template <typename T, typename... Args>
class B : public CRTP::Base<Interface, void>::Derived<B, T, Args...>
{
friend typename CRTP::Friend<Interface, B, void>::Base;
void f() {}
};
Next is an example for when the base depends on template parameters of the derived. The only difference from the previous example is the template keyword. An experiment shows that if the keyword is specified for the previous, non dependant, case the code also complies cleanly.
//Templated derived with extra dependant types passed to the base
//Notice the addition of the "template" keyword
template <typename... Args>
class C : public CRTP::Base<Interface, Args...>::template Derived<C, Args...>
{
friend typename CRTP::Friend<Interface, C, Args...>::Base;
void f() {}
};
Please note that these templates do not work for non-templated derived classes. I will update this answer when I find the solution, so a unified syntax could be used for all cases. The closest thing that can be done is just using some fake template parameter. Note that it still must be named and passed to the CRTP machinery. For example:
template <typename Fake = void>
class D : public CRTP::Base<Interface>::Derived<D, Fake>
{
friend typename CRTP::Friend<Interface, D>::Base;
void f() {}
};
Note that A, B, C & D are declared as class. That is, all their members are private.
Follows is some code that uses the above classes.
template <typename... Args>
void invoke(Interface<Args...> & base)
{
base.f();
}
int main(int, char *[])
{
{
A derived;
//Direct invocation through cast to base (derived.f() is private)
static_cast<A::CRTP &>(derived).f();
//Invocation through template function accepting the base
invoke(derived);
}
{
B<int> derived;
static_cast<B<int>::CRTP &>(derived).f();
invoke(derived);
}
{
C<void> derived;
static_cast<C<void>::CRTP &>(derived).f();
invoke(derived);
}
{
D<void> derived;
static_cast<D<>::CRTP &>(derived).f();
invoke(derived);
}
return 0;
}
The invoke free-standing templated function works for any class derived from the base.
Also shown is how to cast the derived to the base without the need to actually specify the name of the base.
Surprisingly, this does not depend on any system headers.
The full code is available here: https://gist.github.com/equilibr/b27524468a0519aad37abc060cb8bc2b
Comments and corrections are welcome.

Template specialization with polymorphism

I'm wanting to invoke a specialized templated function by using a pointer to it's base type. I'm not sure if this possible so I'm open to suggestions and/or alternatives. Here is an example of my situation:
class CBase {};
class CDerivedClass : public CBase {};
template<class T>
int func<T>(T &x) { ... };
template<>
int func<CDerivedClass>(CDerivedClass &x) { ... };
I have another function that manages a list of CBase pointers and then calls the func() function.
void doStuff()
{
CBase *foo[10] = { ...... };
for (int i = 0; i < 10; ++i)
func(*foo[i]);
}
Is there a way to get the derived type, so that func(CDerivedClass &) is called?
What about Template Subclassing? This idiom allows you to use compile-time polymorphism in C++. The cost of it is higher verbosity (such as specifying the whole class hierarchy up to the current class). In your case:
template <typename TSpec> class Klass {};
template <typename TSpec> struct SpecTag {};
template <typename TSpec> class Klass<SpecTag<TSpec> > {};
template <typename TSpec>
int func(Klass<TSpec> &x) { ... };
template <typename TSpec>
int func(Klass<SpecTag<TSpec> > &x) { ... };
The "Visitor" pattern comes to the rescue in this case. It enables polymorphic behavior in an algorithm implemented outside the class. Some support code is required inside the class, but new algorithms can later be added, existing algorithms modified, etc., without affecting the class.
Alternative solution : from your example, it's obvious that you just should to use a virtual method in CBase, so you just have to define a virtual function in CBase and an overriding function in the derived class.

specializing on a subset of types in a C++ template

I have a question about template specialization in C++, and I am hoping someone here can help. I have a class that has 3 template parameters:
template<class A, class B, class C>
class myClass {
public:
void myFunc();
};
What I want to do is write several versions of myFunc that specialize on, say, type C, but are generic for types A and B. So I do NOT want the fully templated function like this:
template<class A, class B, class C>
void myClass<A, B, C>::myFunc()
{
// function code here
}
and I do NOT want a fully specialized function like this
void myClass<int, int, int>::myFunc()
{
// code goes here
}
Instead, I want to do something that would be similar to
template<class A, class B>
void myClass<A, B, int>::myFunc()
{
// code goes here
}
The idea is that if class type C is int, I would call one version of myFunc(), and if class type C is double, I would call a different version of myFunc. I've tried lots of difference combinations of template specialization syntaxes (too many to list here), and none seems to compile.
Could someone possibly point me in the right direction here? Thanks in advance for your help.
Michael
You can write a function template, and an overload, and delegate the work to it:
template<class A, class B, class C>
class myClass
{
//resolver doesn't need to define anything in it!
template<class> struct resolver {}; //empty, yet powerful!
public:
void myFunc()
{
doFun(resolver<C>());
}
//this is a function template
template<typename X>
void doFun(const resolver<X> & )
{
//this function will get executed when C is other than int
//so write your code here, for the general case
}
//this is an overload, not a specialization of the above function template!
void doFun(const resolver<int> & )
{
//this function will get executed when C = int
//so write your code here, for the special case when C = int
}
};
Note an important point : doFun(const resolve<int>& ) is an overloaded function, its not a specialization of the function template. You cannot specialize member function template without specializing the enclosing class template.
Read these articles:
Template Specialization and Overloading
Why Not Specialize Function Templates?
Dispatching on a resolver type as #Nawaz shows is IMHO the best way. Another option would be to move the real implementation of that function outside of the class, inside its own struct, make it static and partially specialize the struct. Inside the class, call that. Of course, if it accesses private parts of myClass, you need to make it friend:
template<class A, class B, class C>
class myClass;
template<class A, class B, class C>
struct myClassFuncs{
typedef myClass<A,B,C> class_type;
static void myFunc(class_type* self){
// generic for everything ...
}
};
template<class A, class B>
struct myClassFuncs<A,B,int>{
typedef myClass<A,B,int> class_type;
static void myFunc(class_type* self){
// specialized on C == int ...
}
};
// and so on ...
template<class A, class B, class C>
class myClass{
typedef myClassFuncs<A,B,C> func_holder;
friend class func_holder;
public:
void myFunc(){
func_holder::myFunc(this);
}
};
Though that leads to a lot of wrappers in the class and the specialized versions...
Another idea, which can be said to be pretty crazy, is to not have functions in the class but functors. Those get specialized and then called. This is more verbose, but allows a better access to which functions you want to specialize. Though, if they want to access private parts, you now need to make all of them friends. :/
template<class A, class B, class C>
class myClass;
template<class A, class B, class C>
class myClass_myFunc{
typedef myClass<A,B,C> class_type;
class_type* const _self;
public:
myClass_myFunc(class_type* self)
: _self(self)
{}
void operator() const{
// generic logic here
}
};
template<class A, class B>
class myClass_myFunc<A,B,int>{
typedef myClass<A,B,int> class_type;
class_type* const _self;
public:
myClass_myFunc(class_type* self)
: _self(self)
{}
void operator() const{
// specialized logic here
}
};
template<class A, class B, class C>
class myClass{
friend class myClass_myFunc<A,B,C>;
public:
myClass()
: myFunc(this)
{}
const myClass_myFunc<A,B,C> myFunc;
};