Seite 1 von 1

function template overload resolution und dependant names

Verfasst: 04.07.2013, 18:22
von kaiserludi
Moin.

In folgendem Code wird von VC++ wie gewünscht das Template ausgewählt:

Code: Alles auswählen

struct FooBar
{
};

class Foo
{
public:
	template<typename T> static void bar(T t){}
	static void bar(FooBar b){}
};

int main(void)
{
	Foo foo;
	foo.bar(1);
}
Hier hingegen wird von VC++ plötzlich der Overload für FooBar gewählt, obwohl er gar nicht passt:

Code: Alles auswählen

struct FooBar
{
};

class Foo
{
public:
	template<typename T> static void bar(typename std::enable_if<!std::is_pointer<T>::value,T>::type t){}
	static void bar(FooBar b){}
};

int main(void)
{
	foo::bar(1);
}
Entsprechend gibts eine Fehlermeldung
error C2664: 'void Foo::bar(FooBar)' : cannot convert parameter 1 from 'int' to 'FooBar'
Jemand eine Idee, wieso das so ist und wie man den Compiler dazu bekommt, trotzt dependant name lookup das Template zu wählen?

Edit:
Code simplifiziert und vereinheitlicht.

Edit2: überflüssige Semikola entfernt.

Re: function template overload resolution und dependant name

Verfasst: 04.07.2013, 18:44
von CodingCat
Morgen
Deduktion von Template-Argumenten geht NUR in reiner Typkonstruktornotation. Sobald du abhängige Namen nutzt, schaltest du für den entsprechenden Parameter automatisch Deduktion ab (Deduktion wäre hier von Seiten des Compilers auch kaum sinnvoll umzusetzen). In C++11 tust du folgendes:

Code: Alles auswählen

template <
   typename T,
   typename = typename std::enable_if<!std::is_pointer<T>::value>::type
> static void bar(T t) { }
Heute
Da dein VC mit großer Wahrscheinlichkeit noch nicht auf dem notwendigen Stand ist, musst du dich mit folgendem begnügen:

Code: Alles auswählen

template <
   typename T
> static typename std::enable_if<!std::is_pointer<T>::value, void>::type bar(T t) { }
Übermorgen
Mit C++14 ginge mit Template-Variablen und constexpr eventuell folgendes:

Code: Alles auswählen

template <
   typename T,
   typename = typename imaginary_std::enable_if<!imaginary_std::is_pointer<T>>::type
> static void bar(T t) { }
Ich befürchte aber, eine solche verbesserte imaginary_std wird nicht so bald mitgeliefert.

Weiterhin wird momentan an Concepts Lite gewerkelt, die es ebenfalls noch in C++14 schaffen könnten(?):

Code: Alles auswählen

template <imaginary_std::NoPointer T>
static void bar(T t) { }
oder

Code: Alles auswählen

template <typename T> requires !imaginary_std::IsPointer<T>()
static void bar(T t) { }
oder

Code: Alles auswählen

template <typename T> requires !std::is_pointer<T>::value
static void bar(T t) { }

Re: function template overload resolution und dependant name

Verfasst: 04.07.2013, 20:35
von kaiserludi
"Morgen" erzeugt mir:
error C4519: default template arguments are only allowed on a class template
"Heute" funzt. Mag zwar nicht super schick sein, die Validierung des Parameters beim Returntype zu machen (und ich wäre von alleine wohl auch nicht so schnell auf die Idee gekommen), aber es funktionert und ist verständlich und das reicht mir in diesem Fall mehr als aus.

"Übermorgen" Nummer 2 wäre natürlich ideal, aber das ist dann wohl noch Zukunftsmusik.

Ich schulde dir ein weiteres Bier :mrgreen: