Std::map of member function pointers

Dear all,

I would like to use a std::map of pointers to member functions. My class is derived from TSelector.

#include <map>
#include <string>

#include <TNamed.h>
#include <TSelector.h>


class testMap;
//typedef Float_t (testMap::*func_ptr)();

#ifdef __CINT__

#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;

#pragma link C++ class testMap+;
//#pragma link C++ class map<string, testMap::*func_ptr>+;

#endif


class testMap: public TSelector
{

	typedef Float_t (testMap::*func_ptr)();
	std::map< std::string, func_ptr >			m;
	std::map< std::string, func_ptr >::iterator	m_it;

	Float_t mjj;
	
	inline Float_t getMJJ(){ return mjj; }

	/* ... */

public:
	
	testMap()
	{
		m["mjj"] = &testMap::getMJJ;
	}
	
	/* ... */
	
	inline Float_t getVar( TNamed* vD )
	{
		// My use case is more complex...
		
		m_it = m.find(vD->GetName());
		if( m_it != m.end() ) return (this->*this->m_it->second)();
		
		return -99.;
	}
	
	/* ... */

};

Here are the errors I get.

root [0] .L testMap.C+
Info in <TUnixSystem::ACLiC>: creating shared library /Users/karolos/data/LargeAnalysisCode/src/test/./testMap_C.so
Error: Symbol G__p2memfuncsecond is not defined in current scope  /Applications/root_v5.26.00/cint/cint/lib/prec_stl/utility:19:
Error: class,struct,union or type G__p2memfunc not defined  /Applications/root_v5.26.00/cint/cint/lib/prec_stl/map:66:
Error: Symbol G__p2memfuncsecond is not defined in current scope  /Applications/root_v5.26.00/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing /Users/karolos/data/LargeAnalysisCode/src/test/./testMap_C_ACLiC_dict.cxx /Users/karolos/data/LargeAnalysisCode/src/test/./testMap_C_ACLiC_dict.h !!!
Error: /Applications/root_v5.26.00/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Info in <ACLiC>: Invoking compiler to check macro's validity
Info in <ACLiC>: The compiler has not found any problem with your macro.
	Probably your macro uses something rootcint can't parse.
	Check http://root.cern.ch/root/Cint.phtml?limitations for Cint's limitations.
root [1] 

I’ve been going a bit into the map header and saw that the problem is at a line that attempts

typedef T mapped_type;

and then the utility header tries to use

Could it be a simple space issue, i.e that G__p2memfuncsecond should be G__p2memfunc second (extra space) ?

I have tried to use pragma and to move the typdef to a global one without success. This is the farthest as I could get.

I am not familiar with the inner workings of CINT and I also understand that this is a limit use case. Is there a workaround to this or is this something that requires a modification in CINT ?

I have also tried to compile my library as a shared class but I couldn’t load it:

root [0] .L testMap.so 
dlopen error: /home/karolos/data/LargeAnalysisCode/src/test/./testMap.so: undefined symbol: _ZN9testMap201011ShowMembersER16TMemberInspectorPc
Load Error: Failed to load Dynamic link library /home/karolos/data/LargeAnalysisCode/src/test/./testMap.so
*** Interpreter error recovered ***

Is there a way to manually add this TMemberInspector object, i.e. make my dictionary manually ? I tried to figure out if it was possible for rootcint to provide me with the dictionary it was able to generate instead of deleting it in order to have a look myself but without success.

The whole point of what I’m doing is to use Proof and submit my analysis. The code would be anyhow compiled and there is only the getVar that CINT needs to be aware of. Is it possible to mask the inner details of using a map ? Also, I don’t know on which line CINT fails ; is there a way to get a verbose output to makecint ? The man page doesn’t seem to suggest anything like that.

Thanks for your help,
Karolos

[quote]Is there a way to manually add this TMemberInspector object, i.e. make my dictionary manually ? [/quote]You would need to create a dictionary via an explicit call to rootcint but you are likely to encounter the same problem as you originally did. You could also remove the ClassDef from the class definition. But either way if you do not generate a dictionary your class will not be available from the interpreter.

[quote]I would like to use a std::map of pointers to member functions. My class is derived from TSelector.

Here are the errors I get.[/quote]Unfortunately CINT does not handle function pointer very well and it is not too surprising that this combination does not work. The best solution is to hide this data member from CINT altogether:

class testMap: public TSelector { #ifndef __CINT__ typedef Float_t (testMap::*func_ptr)(); std::map< std::string, func_ptr > m; std::map< std::string, func_ptr >::iterator m_it; #endif

Cheers,
Philippe.

Thank you very much for your reply and suggestions Philippe.

I was able to have it compile both in CINT and using makecint. Do I need a helper function to access the part “hidden” to CINT or is it OK if I provide a definition of the function that reaches the hidden map ?

Karolos

[quote] is it OK if I provide a definition of the function that reaches the hidden map ?[/quote]Yes this is sufficient.

Cheers,
Philippe.

Hi,

Is there a way how to create a std::map of just function pointers? Something like:

ROOT 5.34/09 (heads/v5-34-00-patches@v5-34-09-196-g20a7411, Aug 16 2013, 17:34:33 on linuxx8664gcc)
root [0] #include <map>
root [1] Double_t (*FunPtr)(const Double_t) const;
root [2] std::map<TString,FunPtr> mymap;

which, however, gives this error

Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing /home/jiri/work/tmp/AutoDict_pair_const_TString_FunPtr__cxx_ACLiC_dict.cxx /home/jiri/work/tmp/AutoDict_pair_const_TString_FunPtr__cxx_ACLiC_dict.h !!!
Error: /opt/rootgit3/root/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Error: Invalid type 'FunPtr' in declaration of 'second' _pair.h:34:
Error: Symbol FunPtr second is not defined in current scope  _pair.h:34:
Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.cxx /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.h !!!
Error: /opt/rootgit3/root/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.cxx /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.h !!!
Error: /opt/rootgit3/root/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Warning: Error occurred during dictionary source generation
!!!Removing /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.cxx /home/jiri/work/tmp/AutoDict_allocator_pair_const_TString_FunPtr____cxx_ACLiC_dict.h !!!
Error: /opt/rootgit3/root/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Error: class,struct,union or type FunPtr not defined  /opt/rootgit3/root/cint/cint/lib/prec_stl/map:66:
Error: Symbol FunPtr second is not defined in current scope  /opt/rootgit3/root/cint/cint/lib/prec_stl/utility:19:
Warning: Error occurred during reading source files
Note: Link requested for undefined class map<TString,FunPtr,less<TString>,allocator<pair<const TString,FunPtr> > >::mapped_type (ignore this message) :0:
Warning: Error occurred during dictionary source generation
!!!Removing /home/jiri/work/tmp/AutoDict_map_TString_FunPtr_less_TString__allocator_pair_const_TString_FunPtr______cxx_ACLiC_dict.cxx /home/jiri/work/tmp/AutoDict_map_TString_FunPtr_less_TString__allocator_pair_const_TString_FunPtr______cxx_ACLiC_dict.h !!!
Error: /opt/rootgit3/root/bin/rootcint: error loading headers...
Error in <ACLiC>: Dictionary generation failed!
*** Interpreter error recovered ***

Or is it still not possible to create such std::map even with newer versions of ROOT?

Cheers,
Jiri

Hi Jiri,

The easiest way to do this in CINT is to store the function pointer as a void*.

Cheers,
Philippe.