Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Redefinition" of default template parameter

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.

like image 761
Synxis Avatar asked Sep 29 '12 20:09

Synxis


People also ask

Can template have default parameters?

Template parameters may have default arguments. The set of default template arguments accumulates over all declarations of a given template.

Why do we use template template parameter?

8. Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)


1 Answers

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.

like image 104
Christian Stieber Avatar answered Oct 15 '22 16:10

Christian Stieber