Showing posts with label templates. Show all posts
Showing posts with label templates. Show all posts

Monday, October 3, 2016

template: detect required argument type of a function and adapt the data consequently

Example: classes' operator () can receive either a type G or a I<G>.
We pass either the argument I<G> or its member x of type G to operator () depending on what the operator is able to take

#include <iostream>

template <typename G> class I{
public:
  G x;
};


template<typename G>
class Caller{   
public:
  template<typename C>
  static void pass(C& c,I<G>& i){c(i.x);}

};

template<typename G>
class Caller<I<G> >{   
public:
  template<typename C>
  static void pass(C& c,I<G>& i){c(i);}
};


template<typename C,typename X>
X getArgumentType(void (C::*f)(X));

template<typename C,typename G>
inline void call(C& c,I<G>& i){
  Caller<typeof(getArgumentType(&C::operator()))>::pass(c,i);
}

 

struct A{
  void operator()(int x){
    std::cout<<"This is A "<<x<<std::endl;
  }
};

struct B{
  void operator()(I<int>& y){
    std::cout<<"This is B "<<y.x<<std::endl;
  }
};



int main(){

  A a;
  B b;
  I<int> y;
  y.x=77;
  call(a,y);
  call(b,y);
}

Sunday, September 2, 2012

precedence of template over constructor


#include <iostream>

struct C{
};


struct D{
  D(const C&){}
};


struct A{
  template<typename T> void p(const T& t){
    std::cout<<"template "<<std::endl;
    }
 
  void p(const D& t){
    std::cout<<"constructor "<<std::endl;
  }
};



int main(){
  A a;
  C c;
  a.p(c);
}
=====OUTPUT=====
template

Thursday, June 21, 2012

Using a function of a superclass as template param is not allowed


struct A{
  void f(){}
};

struct B:public A{
};


template<typename C,void (C::*f)()>
struct Call{

  void operator()(C* c){
    (c->*f)();
  }
};


int main(){
  B b;
  Call<B,&B::f> a;
  a(&b);

}

====Compiler output===
 error: could not convert template argument ‘&A::f’ to ‘void (B::*)()’



~~~~~~~INSTEAD~~~~~~

 void (B::*f)()=&B::f; works


Wednesday, June 20, 2012

emulate virtual methods by templates


#include <iostream>
using namespace std;



template<typename T> struct D{
  void f(){cout<<"d::f"<<endl;}
  void g(){
    static_cast<T*>(this)->f();
  }
};



struct A:public D<A>{
  void f(){cout<<"A::f"<<endl;}
};

struct B:public D<B>{
};

int main(){

  A a;
  B b;

  a.g();
  b.g();

}

=====Output======
A::f
d::f

Tuesday, May 15, 2012

Determine if a class has a template specialization



#include<iostream>

template<typename T>
struct A{
  typedef int NotSpecialized;
};


template<typename T>
struct isSpecialized{
  typedef char yes;
  typedef char no[2];
  template<typename F>
  static no& test(typename F::NotSpecialized);
  template<typename F>
  static yes& test(double);
  static const bool value=(sizeof(test<T>(0))==sizeof(yes));
};


template<>
struct A<bool>{
};


int main(){
 
  std::cout<< isSpecialized<A<char> >::value<<" "<<isSpecialized<A<bool> >::value<<std::endl;

}


===output====

0 1

Thursday, May 10, 2012

template function in template class


template <bool b>
struct A{
  template<typename T> void f(const T& t);
};

template<> template<typename T>
void A<false>::f(const T& t){
}


int main(){
  A<false> a;
  a.f(3);
}

^^^^^^^^^^^^^^^^^^^^^^^^
This does NOT work anymore for partial specialization

template<typename T,bool x>
struct A{

  void f();

};


template<typename T>
void A<T,true>::f(){
}


template<typename T>
void A<T,false>::f(){
}

===COMPILER OUTPUT===



funcSpec.cpp:126:19: error: invalid use of incomplete type ‘struct A<T, true>’
funcSpec.cpp:118:8: error: declaration of ‘struct A<T, true>’
funcSpec.cpp:131:20: error: invalid use of incomplete type ‘struct A<T, false>’
funcSpec.cpp:118:8: error: declaration of ‘struct A<T, false>’



^^^^^^^^^^^^^^^^^^^^^^^
Similarly, you cannot "group" after specializing




template<bool b>
struct A{
  void f();
};

template<>
struct A<true>{
  void f();
};


template<bool b> void A<b>::f(){
}


int main(){
  A<true> a;
  a.f();
};


===COMPILER OUTPUT=====

tmp/ccsJCUcq.o: In function `main':
/home/fabio/research/software/src/helium/tests/funcSpec2.cpp:23: undefined reference to `A<true>::f()'



Saturday, May 5, 2012

template argument involves template parameter(s)

A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier.




template<typename T> struct DefOpt{
  static const int value=0;
};


template<typename T> struct DefClass{
  typedef T DefT;
};




template<typename T,typename V=typename DefClass<T>::DefT,int val=DefOpt<T>::value> 
struct DefAccPol{
};




template<typename T>
struct A{
};




template<>
struct DefAccPol< int >{
};




template<typename T>
struct DefAccPol< A<T> >{
};




int main(){
  DefAccPol<A<int> > at;


}


===compiler output===
error: template argument ‘DefOpt<A<T> >::value’ involves template parameter(s)

the reason int val=DefOpt<T>::value


the type (DefClass<T>::DefT) is fine.

template<>
struct DefAccPol< int >{
}; 
is fine as well, because it has no templates 
only the combination of int val=.. and template<typename T> partial specialization is bad

similarly


template<typename T>
struct DefAccPol< A<T>,T,DefOpt<T>::value >{
};


is not accepted, but


template<typename T>
struct DefAccPol< A<T>,T,0 >{
};

is ok

Tuesday, May 1, 2012

Specialization of a single function


#include <iostream>



template<typename T>
struct A{
  void f();
};

template<typename T>
void A<T>::f(){
  std::cout<<"generic"<<std::endl;
}


template<>
void A<int>::f(){
  std::cout<<"int"<<std::endl;
}


int main(){
  A<int> x;
  x.f();
  A<double> d;
  d.f();
}

====output====

int
generic