Seite 1 von 1

Template function matching

Verfasst: 15.06.2012, 13:54
von eXile
Ich versuche mich mal wieder in der Welt der Templates, aber irgendwie scheine ich das Herleiten von Template-Argumenten noch nicht ganz verstanden zu haben:

Code: Alles auswählen

#include <iostream>
 
template <typename T1, T1 value>
class Class1
{
public:
        template <typename T2>
        class Class2
        {
        public:
                explicit Class2(
                        T2 theValue
                ) : myValue(theValue)
                {
                        return;
                }
 
                template <typename T1Other, T1Other valueOther, typename T2Other>
                inline Class2(
                        typename Class1<T1Other, valueOther>::template Class2<T2Other> const & other
                ) {
                        myValue = other.myValue;
                }
 
                template <typename T1Other, T1Other valueOther, typename T2Other>
                inline bool operator==(
                        typename Class1<T1Other, valueOther>::template Class2<T2Other> const & other
                ) const {
                        return (myValue == other.myValue);
                }
 
        private:
                T2 myValue;
        };
 
        Class2<T1> const get() const
        {
                return Class2<T1>(value);
        }
};
 
int main(int argc, char * argv[])
{
        Class1<int, 1> c1;
        Class1<int, 2> c2;
 
        std::cout << (c1.get() == c2.get());
}
Ergibt unter Visual C++:
cl.exe hat geschrieben:error C2783: 'bool Class1<T1,value>::Class2<T2>::operator ==(const Class1<T1Other,valueOther>::Class2<T2Other> &) const' : could not deduce template argument for 'T1Other'
with
[
T1=int,
value=1,
T2=int
]
see declaration of 'Class1<T1,value>::Class2<T2>::operator =='
with
[
T1=int,
value=1,
T2=int
]
bzw. live und in Farbe
g++ hat geschrieben:prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:47: error: no match for ‘operator==’ in ‘c1.Class1<T1, value>::get [with T1 = int, T1 value = 1]() == c2.Class1<T1, value>::get [with T1 = int, T1 value = 2]()’
Eigentlich hätte ich gedacht, dass ich den operator== mit hinreichend vielen Template-Parametern ausgestatten hätte, als dass er zumindest einen Treffer finden kann. Liegt es an den verschachtelten Klassen?

Re: Template function matching

Verfasst: 15.06.2012, 14:06
von CodingCat
eXile hat geschrieben:Eigentlich hätte ich gedacht, dass ich den operator== mit hinreichend vielen Template-Parametern ausgestatten hätte, als dass er zumindest einen Treffer finden kann. Liegt es an den verschachtelten Klassen?
Ich befürchte, ja. Siehe std::identity, das gerade dazu da ist, Deduktion abzuschalten:

Code: Alles auswählen

template<class DontDeduce, class Deduce>
void templateFun(typename std::identity<DontDeduce>::type a, Deduce b);
Du erwartest vom Compiler, dass er eine Instanz vom Class1-Template findet, die ein Class2-Template enthält. Schon in deinem Beispiel gibt es dafür unendlich viele Möglichkeiten. ;)

Re: Template function matching

Verfasst: 15.06.2012, 14:25
von CodingCat
Ich muss mich nochmal korrigieren. Tatsächlich ist Class1<int, 2>:: natürlich Teil des Typs Class1<int, 2>::Class2<int>, insofern darfst du durchaus erwarten, dass der Compiler auch den vollen Typ deduziert. Vermutlich wurde dieser Sonderfall einfach nie ernsthaft in Betracht gezogen.

Re: Template function matching

Verfasst: 15.06.2012, 17:01
von eXile
Gefunden!
C++-Standard, 14.8.2.5 Deducing template arguments from a type hat geschrieben:The non-deduced contexts are:
— The nested-name-specifier of a type that was specified using a qualified-id.
[…]
When a type name is specified in a way that includes a non-deduced context, all of the types that comprise that type name are also non-deduced. However, a compound type can include both deduced and non-deduced types. [Example: If a type is specified as A<T>::B<T2>, both T and T2 are non-deduced. Likewise, if a type is specified as A<I+J>::X<T>, I, J, and T are non-deduced. If a type is specified as void f(typename A<T>::B, A<T>), the T in A<T>::B is non-deduced but the T in A<T> is deduced. —end example]
Es hat also einen Grund, warum man bei Templates häufig verschachtelte Typen vermeidet. Es ist einfach zu gefährlich. Also hat man es anscheinend gleich ganz verboten.

Auf dem Wege dahin habe ich auch noch eine handliche Liste der deduzierbaren Umgebungen gefunden. Vielen Dank für deine Hilfe. ;)

Re: Template function matching

Verfasst: 15.06.2012, 17:11
von dot
Ich bin immer wieder erstaunt darüber, an was die Leute im C++ Standardkommittee alles gedacht haben...

Re: Template function matching

Verfasst: 15.06.2012, 17:51
von CodingCat
dot hat geschrieben:Ich bin immer wieder erstaunt darüber, an was die Leute im C++ Standardkommittee alles gedacht haben...
Naja, in diesem Fall haben sie ja wie vermutet gerade nicht darüber nachdenken wollen, und es einfach verboten. :P
eXile hat geschrieben:Es hat also einen Grund, warum man bei Templates häufig verschachtelte Typen vermeidet. Es ist einfach zu gefährlich. Also hat man es anscheinend gleich ganz verboten.
Ja, der Link beschreibt genau das, was ich in meinem ersten Post angedacht hatte. Ich sehe aber nach wie vor abgesehen von Bequemlichkeit absolut keinen Grund, deinen konkreten Anwendungsfall zu verbieten, weil der Typ und somit auch die Parameter im Falle eines verschachtelten Templates absolut klar sind.