Kan een afgeleid type dezelfde naam hebben als een genest type van zijn basis?

Is de volgende code legaal? MSVC 9 en g ++ 4.4 zijn het daar niet mee eens:

struct base
{
  struct derived {};
};

struct derived : base {};

int main()
{
  typedef derived::derived type;
  return 0;
}

MSVC klaagt, verwarrend de geneste naam voor de constructor van het type:

c:\dev>cl test.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(10) : error C2146: syntax error : missing ';' before identifier 'type'
test.cpp(10) : error C2761: '{ctor}' : member function redeclaration not allowed

test.cpp(10) : error C2065: 'type' : undeclared identifier

Terwijl g ++ niet:

$ g++ --version test.cpp
g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Voor context bevat mijn code een iterator die pointer wordt genoemd. Om de iterator-interface te bieden, biedt deze de geneste type -aanwijzer , wat een synoniem voor zichzelf is.

4
Probeer het met typedef typename derived: afgeleid type; en kijk of het werkt.
toegevoegd de auteur Mark Ransom, de bron
Ik geloof dat typename onwettig is in niet-gemoduleerde code, of dat op zijn minst sommige compilers erover klagen.
toegevoegd de auteur Jared Hoberock, de bron
Sorry, ik heb je code verkeerd gelezen. Trouwens, voor Comeau is je code illegaal (met en zonder typenaam ), dus ik ben geneigd te denken dat VC ++ hier is.
toegevoegd de auteur Matteo Italia, de bron
FWIW gcc 4.6.2 accepteert de code ook niet en geeft een zeer beschrijvende foutmelding.
toegevoegd de auteur pmr, de bron

2 antwoord

Comeau thinks that your code is incorrect, so I think that the constructor-interpretation shadowing the type-interpretation is what the standard mandates1.

Toch compileert je code graag als je de ambiguïteit oplost en de compiler vertelt dat je probeert toegang te krijgen tot het derived -lid van de basisklasse:

struct base
{
  struct derived {};
};

struct derived : base {};

int main()
{
  typedef derived::base::derived type;
  return 0;
}

Overigens klopt het feit dat de constructor-interpretatie nogal klopt: je hebt een bekende manier om de compiler te vertellen dat je naar dingen van de basisklasse wilt verwijzen (via de scope resolution operator), maar dat zou je niet doen ' t heeft een syntaxis om het omgekeerde te doen (dwingt de compiler om te begrijpen dat je naar de constructor verwijst). Dus het 'constructor-per-standaard'-gedrag lijkt redelijk verstandig.


  1. Ik zal het misschien later opzoeken, maar ik kan niet garanderen dat ik het echt zal doen, dit soort vervelende naamkwesties zijn altijd een puinhoop om op te zoeken.
3
toegevoegd
Bedankt! std: iterator_traits verslikt zich helaas. Ik zal het moeten specialiseren denk ik.
toegevoegd de auteur Jared Hoberock, de bron
Ik heb een pointer-wrapper, pointer , die is afgeleid van boost :: iterator_adaptor . De aanwijzer-wrapper codeert metadata in het type systeem.
toegevoegd de auteur Jared Hoberock, de bron
@JaredHoberock: wat probeer je eigenlijk te doen?
toegevoegd de auteur Matteo Italia, de bron

Wat je hebt is een coflict in de namen. Hernoem gewoon de tweede struct om struct derived2 te structureren. En doe deze wijziging ook in main() : typefact afgeleid2 :: afgeleid type; Het compileert zonder fouten in VC ++ 6.0

struct base
{
  struct derived {};
};

struct derived2 : base {};


int main()
{
  typedef derived2::derived type;
  return 0;
}
0
toegevoegd
Ik zou wat code niet controleren op standaard conformiteit met VC ++ 6.0 ...: S
toegevoegd de auteur Matteo Italia, de bron