Gedeeltelijke specialisatie van variadische sjablonen

Beschouw de volgende klassesjabloon 'X' en de deelspecialisaties ervan.

template 
struct X {};              //#1

template 
struct X {};          //#2

template 
struct X {};//#3

X x;                 //#2 or #3 ?

I suspect X is ambiguous. It is because:

Het is duidelijk dat zowel # 2 als # 3 meer gespecialiseerd zijn dan # 1, # 2 en # 3 nu worden vergeleken. Laten we, volgens 14.5.5.2, eens bekijken welke van de volgende # 2 'en # 3' meer gespecialiseerd is.

template 
void f(X);            //#2'

template 
void f(X);  //#3'

According to 14.8.2.4, the first step is the template argument deduction using #2' as the argument template and #3' as the parameter template. Given the only argument type is X, the deduced T1 is A1, and Types is empty.

A = X, P = X  =>  T1 = A1, Types = {}

The second step is done using #3' as the argument template and #2' as the parameter template. Given the only argument type is X, according to 14.8.2.5/9 (note that this paragraph is recently revised by N3281), Args is simply ignored, the deduced T1 is A1 and argument deduction succeeds.

A = X, P = X  =>  T1 = A1 (Args is ignored)

Finally, the bidirectional argument deductions succeeded. So #2 is just as specialized as #3. In conclusion, X is ambiguous.

Mijn vraag is: "is mijn interpretatie correct?"

Als deze interpretatie correct is, is de definitie van 'std :: common_type' in 20.9.7.6/3 ongepast.

template 
struct common_type;           //#1

template 
struct common_type         //#2
{
    typedef T type;
};

template 
struct common_type      //#3
{
    typedef
        decltype(true ? declval() : declval())
    type;
};

template 
struct common_type//#4
{
    typedef typename
        common_type::type, V...>::type
    type;
};

When common_type is used, #3 and #4 are ambiguous.

Opmerking: in het eerste voorbeeld selecteert GCC 4.7.0 (snapshot) en Clang 3.0 # 2. Deze compilers zijn echter zo onbetrouwbaar dat ze de andere wijzigingen door N3281 niet volgen.

42
Het lijkt erop dat je gelijk hebt. Een leeg parameterpakket mag de gedeeltelijke ordening niet beïnvloeden. gcc lijkt dit te negeren en een variadische sjabloon lager in de lijst te plaatsen, terwijl andere dingen gelijk zijn. Bijv. het stelt een voorbeeld samen op 14.5.6.2/5, waarvan expliciet wordt gezegd dat het dubbelzinnig is.
toegevoegd de auteur n.m., de bron
@Aaron: nee, deze . Dit is het laatste voorbeeld van 14.5.6.2. Het compileert hoewel de opmerking duidelijk stelt dat het niet zou moeten.
toegevoegd de auteur n.m., de bron
@Aaron: gedeeltelijke ordening van klassesjablonen wordt uitgedrukt in termen van gedeeltelijke ordening van functiesjablonen, zoals beschreven in 14.5.5.2. Dus het moet op beide van toepassing zijn.
toegevoegd de auteur n.m., de bron
@ N. M. Is deze code waar je het over hebt? Ik heb die code overgenomen van N3242 , zoals gelinkt vanuit Wikipedia
toegevoegd de auteur Aaron McDaid, de bron
14.5.6.2/5 (vanaf N3242) "De aanwezigheid van ongebruikte ellips en standaardargumenten heeft geen effect op de gedeeltelijke ordening van functie sjablonen" (mijn cursivering). Misschien is dit alleen van toepassing op functiesjablonen, terwijl deze vraag over klassesjablonen gaat?
toegevoegd de auteur Aaron McDaid, de bron
@ N. M. In N3242 in 14.5.6.2/5 zeggen ze niet dat het niet moet compileren. Ze lijken het voorbeeld te hebben veranderd in het document waar je naar kijkt.
toegevoegd de auteur Aaron McDaid, de bron
(met andere woorden, ik kijk waarschijnlijk naar een verouderd document, en ik ben hoe dan ook geen expert!)
toegevoegd de auteur Aaron McDaid, de bron
Juistheid is meestal het onderwerp van eenheidscontroles, vooral bij het programmeren. Dit zorgt ervoor dat uw interpretatie juist is en dat u de taalspecificaties begrijpt tot een hoge mate van vertrouwen, die beide hier in het geding zijn.
toegevoegd de auteur djhaskin987, de bron

1 antwoord

14.8.2.4, sectie 11 (ik verwijs naar concept N3242).

In most cases, all template parameters must have values in order for deduction to succeed, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering. [ Note: A template parameter used in a non-deduced context is considered used. —end note ] [ Example:

template  T f(int);//#1
template  T f(U);//#2
void g() {
f(1);//calls #1
}

In jouw geval wordt # 3 gebruikt.

8
toegevoegd