• Template argument name resolution and compiler discrepancies

    From Jonathan Jones@21:1/5 to All on Sat Sep 12 11:24:16 2015
    Hi folks,

    Look at the following example code:

    template<typename>
    class Base
    {
    typedef int ValueType;
    };

    template<typename ValueType>
    struct Derived : public Base<ValueType>
    {
    Derived(ValueType);
    };

    Derived<float> obj(1);

    This code compiles cleanly with GCC 4.7.2 and Clang 3.5 (Xcode 6.2).
    However, it fails to compile with Visual Studio 2013, complaining that it cannot access private typedef "Base<ValueType>::ValueType".

    Furthermore, if you make the private typedef public:

    template<typename>
    class Base
    {
    public:
    typedef int ValueType;
    };

    It compiles on all three compilers, but the produces different answers.
    GCC and clang result in ValueType=float in the Derived constructor
    definition, whereas Visual Studio 2013 results in ValueType=int in the
    Derived constructor definition.

    What does the standard say should happen in these cases? Which compiler(s)
    are closer to implementing the standard behavior?

    The standard is clear (see C++11 section 14.6.1 paragraph 9) about what
    happens when "Base" is not a template, but it seems more vague about when "Base" is a template (which the example above seems to demonstrate).

    Sincerely,
    Jonathan Jones


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Bo Persson@21:1/5 to Jonathan Jones on Sun Sep 13 07:51:24 2015
    On 2015-09-12 19:24, Jonathan Jones wrote:


    Hi folks,

    Look at the following example code:

    template<typename>
    class Base
    {
    typedef int ValueType;
    };

    template<typename ValueType>
    struct Derived : public Base<ValueType>
    {
    Derived(ValueType);
    };

    Derived<float> obj(1);

    This code compiles cleanly with GCC 4.7.2 and Clang 3.5 (Xcode 6.2).
    However, it fails to compile with Visual Studio 2013, complaining that it cannot access private typedef "Base<ValueType>::ValueType".

    Furthermore, if you make the private typedef public:

    template<typename>
    class Base
    {
    public:
    typedef int ValueType;
    };

    It compiles on all three compilers, but the produces different answers.
    GCC and clang result in ValueType=float in the Derived constructor definition, whereas Visual Studio 2013 results in ValueType=int in the Derived constructor definition.

    What does the standard say should happen in these cases? Which compiler(s) are closer to implementing the standard behavior?

    The standard is clear (see C++11 section 14.6.1 paragraph 9) about what happens when "Base" is not a template, but it seems more vague about when "Base" is a template (which the example above seems to demonstrate).


    I would use different names when Base::ValueType is not the same as Derived::ValueType. :-)


    Otherwise, I suspect this is one symptom of VC++ failing to do a proper
    2-phase name lookup. When Base is a template, its ValueType should not be visible in the declaration of Derived(ValueType). If VC++ postpones the
    name lookup until the template is instantiated, it WILL be visible at that point.

    However, as you say, when Base is not a template its ValueType will shadow
    the template parameter in Derived. That's one reason for using a different name.


    Bo Persson


    --
    [ comp.std.c++ is moderated. To submit articles, try posting with your ]
    [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
    [ --- Please see the FAQ before posting. --- ]
    [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)