2016-11-18 3 views
2

Supposons que nous ayons cette structure:Qui est correct ici, GCC ou MSVC?

namespace some_namespace::types { 
    using foo_t = int; 
} 

namespace some_namespace::classes { 
    class bar { 
    public: 
     auto do_stuff() -> types::foo_t; 
    }; 
} 

using namespace some_namespace::classes; 

auto bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

Ce code se compile avec bonheur dans GCC6. Par contre, VS15 avec le commutateur /std:c++latest activé ne reconnaît pas le type de retour . Il renvoie C2653.

Maintenant, ce que je trouve très suspect est que cela se fixe en changeant la seconde moitié à ceci:

using namespace some_namespace; 

auto classes::bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

qui à mes yeux doivent être égaux. Est-ce que je me trompe en pensant que c'est un bug de MSVC? Que dit la norme à ce sujet?

+1

Non seulement GCC et MSVC implémentant un nouveau standard à des débits différents et avec des priorités différentes. –

+0

Je pense que GCC est juste plus indulgent. – Arunmu

+0

Prise en charge de MSVC C++ 17: https://msdn.microsoft.com/en-us/library/hh567368.aspx –

Répondre

4

Cela n'a rien à voir avec la fonctionnalité C++ 17, qui n'a pas touché les directives d'utilisation, ni même les directives d'utilisation. MSVC produit la même erreur de

namespace some_namespace{ 
    namespace types { 
     using foo_t = int; 
    } 
    namespace classes { 
     class bar { 
     public: 
      auto do_stuff() -> types::foo_t; 
     }; 
    } 
} 

using some_namespace::classes::bar; 

auto bar::do_stuff() -> types::foo_t { 
    return 1; 
} 

[basic.lookup.unqual]/8:

Pour les membres d'une classe X, un nom utilisé [...] dans la définition de un membre de classe en dehors de la définition de X, suivant déclarateur-id du membre , est déclaré dans l'une des façons suivantes :

  • avant son utilisation dans le bloc dans lequel il est utilisé, ou dans un bloc d'insertion ([stmt.block]), ou

  • doit être un membre de la classe X ou être un membre d'une classe de base de X ([class.member.lookup]), ou

  • [... deux points de balle sur les classes imbriquées et locales omis ...]

  • si X est membre de l'espace de noms N [.. .], avant l'utilisation du nom, dans l'espace de noms N ou dans l'un des Les espaces de noms englobants.

Nom recherche pour types doit d'abord regarder à l'intérieur bar, puis à l'intérieur classes, puis à l'intérieur some_namespace. Ce dernier devrait trouver l'espace de noms types.