"Redefinition" of default template parameter
Asked Answered
P

1

8

I have a strange compilation warning for the following code, with Visual C++ 2010:

#include <iostream>

class test
{
    public:
        template<class obj>
        class inner
        {
        private:
            // Line 11:
            template<int index, bool unused = true> struct AttributeName;

        private:
            template<bool b>
            struct AttributeName<0,b>
            {
                static inline const char* get()
                {
                    return "prop";
                }
            };

        public:
            typedef AttributeName<0> propname;
        };
        typedef inner<test> description;
};

int main()
{
    test t;
    std::cout << test::description::propname::get(); // Line 32
    return 0;
}

The warning:

file.cpp(11) : warning C4348: 'test::inner<obj>::AttributeName' : redefinition of default parameter : parameter 2 (with [ obj=test ])
file.cpp(11) : see declaration of 'test::inner<obj>::AttributeName' (with [ obj=test ])
file.cpp(32) : see reference to class template instantiation 'test::inner<obj>' being compiled (with [ obj=test ])

What I don't understand is that AttributeName "redefinition" is at the same line than the definition... sounds like a bug

I noticed that making inner a non-template class removes the warning. However, this is not an option since the real code is more complicated than this testcase and need to be templated.

Also, this code won't compile if warning are treated as errors...

It compiles without warnings on GCC.

Why msvc is outputing such warning and is there a workaround ?

edit

The following modification:

template<int index, bool unused = true> struct AttributeName {};

seems to erase the warning.

Piccadilly answered 29/9, 2012 at 20:29 Comment(3)
To the downvoter: please leave a comment on why you down-voted.Piccadilly
Possible duplicate of C++ template function default value.Arius
@PeterMortensen Nope, really not a dup. The question you linked talks about function parameters, while mine talks about template parameters. Furthermore, mine is about a bug...Piccadilly
C
9

This is mostly a guess, as this seems to solve(?) it:

template<int index, bool unused = true> struct AttributeName;
template<int index, bool unused> struct AttributeName
{
};

My guess is that the forward declaration is seen as both a declaration and a "definition" since it can't see anything else, hence it complains about the default being "redefined" even though it's the same line. Could be unintentional, although 2012 behaves the same.

Crossley answered 29/9, 2012 at 21:9 Comment(5)
That seems likely. However, I don't really understand "it can't see anything else"Piccadilly
I have to admit, Christian, I stared at the deductions in this for some time before coming up with the same thing you did. Esp things like: test::description::propname::AttributeName::AttributeName::AttributeName::get() being perfectly legal with this definition.Unhelm
And fwiw no issues on the llvm compiler on a Mac ( would expect the Mac gcc compiler to work by default).Unhelm
Synxis, remember that I'm not a C++ or even MSVC++ expert. Your line 11 is a forward declaration, and you never define anything for it. However, the compiler doesn't actually NEED anything from it either, except for knowing that it exists because you specialize it, so via some weird coincidence in the compiler it doesn't find a definition, goes back to the declaration treating it like the definition, and figures "hey, the default parameter has been declared in the declaration already, so let's warn". Like reading the same book twice, and complaining you already know it :-)Crossley
Can confirm this is a bugOpus

© 2022 - 2024 — McMap. All rights reserved.