[C++0x] Variadic Templates

kickerxy123

Erfahrenes Mitglied
Guten Tag zusammen,


ich habe ein Problem bezüglich Variadic Template Programmierung.
Ich habe mir vor einiger Zeit eine eigene Tuple Klasse geschrieben, die u.a. auch auf std::tuple zurückgreift.

Ich benötige nun eine Funktion, die mir aus dem Tuple das x-te Argument zurückliefert (mit dessem ursprünglichen Datentyp).

Da dachte ich an eine ganz einfache Lösung:
C++:
template<typename ...Tn>
template<std::size_t N>
typename std::enable_if<(N > -1)>::type* CTuple<Tn...>::getS(void)
{

        return ::get<N>(*pTuple); 
 
}
Wenn ich das aufrufe mit:
C++:
template <typename... S, >
		bool test(CTuple<S...>* pOutReturn )
		{
			for(int i = 0; i < pOutReturn->getSize(); i++)
			{
				pOutReturn->getS<i>();
                                //do domething
			}
}

//main:
int d,e,f;
CTuple<int*,int*,int*>* a = new CTuple<int*,int*,int*>(&d,&e,&f);
test(a);

Dann erhalte ich folgende Fehlermeldung:

Invalid operands of type "<unresolved overloaded function type>" and "long unsigned int" to binary "operator<"



Kann mir da bitte wer weiterhelfen?
Ich denke es ist nur eine Kleinigkeit...





Danke sehr und VG
kickerxy



edit:

ich habe meine Funktion nochmal geändert. Ich denke diese neue Art der Deklaration mit auto/decltype ist hier genau richtig!
C++:
template<std::size_t N>
auto getS(void) -> decltype(::get<N>(*(this->pTuple)))
{

        return ::get<N>(*pTuple); 
 
};
}

Jetzt erhalte ich bei
C++:
pOutReturn->getS <2> ( );
expected primary expression before ")" token
und weiterhin Invalid operands of type "<unresolved overloaded function type>" and "long unsigned int" to binary "operator<"
 
Zuletzt bearbeitet:
Servus,

Ich muss leider sagen, dass ich mich mit c++0x noch überhaupt nicht auskenne. Aber die Fehlermeldung klingt wie als ob der Compiler das "<" falsch interpretiert. Er sieht das als kleiner-Operator an und nicht als template-Klammer. Schreib einmal vor den Ausdruck "typename", das sollte das Problem lösen.

Ich hoffe ich konnte dir helfen.

Lg
 
Hallo,

danke für deine Antwort. Ich habe einiges versucht und es klappte dennoch nicht. Allerdings habe ich Fortschritte machen können:

C++:
template<std::size_t N, typename ...Tn> static
auto getS(CTuple<Tn...>* t) -> decltype(std::get<N>(*(t->getTuple())))
{
   return std::get<N>(*(t->getTuple()));
}

rufe ich das nun auf mit
C++:
 getS<0, S...> (pointerAufEinCTuple);
läuft es, wie gewünscht. Problem jetzt:
logischerweise kann ich nur konstante Werte bei getS<> einfügen. Ich muss aber die "0" dynamisch bauen. Daher habe ich folgendes versucht:
C++:
template<std::size_t N, typename ...Tn> static
auto getS(CTuple<Tn...>* t, int n) > decltype(std::get<N>(*(t->getTuple())))
{
	if(n == N)  return std::get<N>(*(t->getTuple()));
	else     	return getS<N-1, Tn...>(t, n);
}
Der Code wäre fertig. Natürlich geht es so nicht, da er in eine unendliche Rekursion läuft beim Versuch das Template beim Compilieren aufzulösen. Verwende ich nun statt auto/trailing return specification ein std::enable_if mit Switch <(N>=0)> und eine weitere Spezialisierung mit N <=0 kompiliert alles wunderbar. Haken dabei: der Returntyp passt nicht mehr (ich verwende: typename std::enable_if<(N > 0)>::type*) -->läuft auf void* hinaus.

Was ich also brauche ist eine Kombination aus enable_if um nicht in eine unendliche Rekursion zur Kompilierzeit zu laufen sowie ein trailing return, um den richtigen Datentyp zu ermitteln.

Hat jemand Vorschläge?

lg
kickerxy



#edit:


C++:
template <std::size_t N, typename ...Tn>
static auto getS(CTuple<Tn...>* t, int n ) -> typename std::enable_if< (N > 0) , decltype(std::get<N>(*(t->getTuple())))>
{
	if(n == N) 	return std::get<N>(*(t->getTuple()));	
	else			return getS<N - 1, Tn...>(t, n);
}

template <std::size_t N, typename ...Tn>
static auto getS(CTuple<Tn...>* t, int n ) -> typename std::enable_if< (N <= 0) , decltype(std::get<0>(*(t->getTuple())))>
{
	return std::get<0>(*(t->getTuple()));	
}
- sieht ganz gut aus, läuft aber auf "ambigious definition" hinaus.


C++:
template <std::size_t N, typename ...Tn, typename _ = typename std::enable_if< (N > 0) >::type >
static auto getS(CTuple<Tn...>* t, int n ) -> decltype(std::get<N>(*(t->getTuple())))
{
	if(n == N) 	return std::get<N>(*(t->getTuple()));	
	else			return getS<N - 1, Tn...>(t, n);
}

template <std::size_t N, typename ...Tn, typename _ = typename std::enable_if< (N <= 0) >::type >
static auto getS(CTuple<Tn...>* t, int n ) -> decltype(std::get<N>(*(t->getTuple())))
{
	return std::get<0>(*(t->getTuple()));	
}
- erhalte ich redefinition.


Ich denke, dass ich kurz vor der Lösung stehe, aber es will einfach nicht ;-)











edit:


Jawohl, es geht :) Habe den kleine "Hack" im Internet gefunden enable_if als dummy Parameter zu nutzen ->dadurch kommt es logischerweise nicht mehr zu Redefinitions, anders als wenn man das zum Return Type packt!

Wen es interessiert zur Vollständigkeit halber:

C++:
template <std::size_t N, typename ...Tn >
static auto getS(CTuple<Tn...>* t, int n, typename std::enable_if< (N > 0) >::type* dummy=0 ) -> decltype(std::get<N>(*(t->getTuple())))
{
	if(n == N) 	return std::get<N>(*(t->getTuple()));	
	else			return getS<N - 1, Tn...>(t, n);
}

template <std::size_t N, typename ...Tn>
static auto getS(CTuple<Tn...>* t, int n, typename std::enable_if< (N <= 0) >::type* dummy=0 ) -> decltype(std::get<0>(*(t->getTuple())))
{
	return std::get<0>(*(t->getTuple()));	
}


VG
 
Zuletzt bearbeitet:
Zurück