Creating dictionaries for templates

I have two templated classes:

template <typename VALUETYPE>
class A{
	VALUETYPE value;
public:
	void setValue(VALUETYPE v){value = v;}
};

template <typename ELEMENTTYPE,int N>
class Container{
	typedef std::vector<ELEMENTTYPE> ELEMENTVECTOR;
	ELEMENTVECTOR elements;
public:
	void setValues(ELEMENTVECTOR in){
		for (int i=0;i<N;i++){ elements[i].setValue(in[i]); }
	}
	void setCalibration(double offset,double factor){
		for (int i=0;i<N;i++){ elements[i].setCalibration(offset,factor); }
	}
};

and I instantiate the template e.g. via

As you can see, the class A does not have a method called setCalibration(). Nevertheless, this compiles and runs without problems, because I never call test.setCalibration() (but I use the same Container with other classes, that support setCalibration() and if possible I would like to keep it like that).

The problem arises when I want to store the Container in a root tree and try to create the dictionary via

#pragma link C++ class Container<A<double>,15>+;

I have to admit, that I do not fully understand the process of creating the dictionary. However, when I try to compile, I get loads of error messages (the above is just a shortened version of the original code) complaining about no matching function calls etc.

Is there a way to avoid this problem?

Hi,

Could you post the error messages you get?

Cheers, Axel.

I was a bit too fast in writing the question, the code above contains some non relevant stuff. However, this …

class A{};
template <typename ELEMENTTYPE,int N>
class Container{
	std::vector<ELEMENTTYPE> elements;
 public:
	void setCalibration(double offset,double factor){
		for (int i=0;i<N;i++){
			elements[i].setCalibration(offset,factor);
		}
	}
};

Container<A,15> test;

…and this…

#pragma link C++ class Container<A,15>+;

…reproduces the error, which says:

./test.h: In instantiation of 'void Container<ELEMENTTYPE, N>::setCalibration(double, double) [with ELEMENTTYPE = A; int N = 15]':
G__SCN.cxx:6699:133:   required from here
./test.h:13:4: error: 'class A' has no member named 'setCalibration'

Please note that the code (without the #pragma link C++…) is perfectly valid C++ (as long as I dont not call Container<A,15>::setCalibration()) but the problem only arises when I want to create the dictionary.
In the meantime, I could fix the error by surrounding the “problematic” method with

#ifndef __CINT__
void setCalibration(double offset,double factor){ /*...*/ }
#endif

This is fine for me, because I only need the data members to be included in the dictionary. However, I still wonder if there is a better way to avoid this problem. It seems like cint tries to instantiate the method which is ill-formed and which actually should not be instantiated, because it is never called.

Hi,

[quote] It seems like cint tries to instantiate the method which is ill-formed[/quote]CINT has no way of knowing that it is ill formed and CINT’s implementation does not allow for the late instantiation (of wrapper to compile code) and the only option are to hide this function from CINT (as you did) or to disable the dictionary generation for all function of that class (but then no member function will be available at run-time.

Note that in ROOT v6, the problem does not exist as Cling is able to delay the instantiation of the member function until they are actually used.

Cheers,
Philippe.