Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can template<T> but not template<> be defined outside of a namespace block?

Tags:

Here is some code which does not compile.

namespace ns
{
    class foo
    {
        template <typename T> int bar (T *);
    };
}

template <typename T>
int ns :: foo :: bar (T*) // this is OK
{
    return 0;
}

template <>
int ns :: foo :: bar <int> (int *) // this is an error
{
    return 1;
}

The error is: "specialisation of ‘template int ns::foo::bar(T*)’ in different namespace [-fpermissive] from definition of ‘template int ns::foo::bar(T*)"

Here is a version which does compile:

namespace ns
{
    class foo
    {
        template <typename T> int bar (T *);
    };
}

template <typename T>
int ns :: foo :: bar (T*)
{
    return 0;
}

namespace ns
{
    template <>
    int foo :: bar <int> (int *)
    {
        return 1;
    }
}

Why does the second definition have to be in a namespace ns {} block when the first one is quite happily defined with a qualified name? Is it just an oversight in the language design or is there a reason for this?

like image 231
spraff Avatar asked Aug 18 '13 01:08

spraff


People also ask

What is template struct in C++?

C++ templates make an algorithm independent of the type of data employed. The entities of variable, function, struct, and class can have templates, which involve declaration and definition. Creating a template also involves specialization, which is when a generic type takes an actual type.

When use template C++?

Templates in c++ is defined as a blueprint or formula for creating a generic class or a function. To simply put, you can create a single function or single class to work with different data types using templates. C++ template is also known as generic functions or classes which is a very powerful feature in C++.

How do you declare a template?

To instantiate a template class explicitly, follow the template keyword by a declaration (not definition) for the class, with the class identifier followed by the template arguments. template class Array<char>; template class String<19>; When you explicitly instantiate a class, all of its members are also instantiated.

How many types of templates are there in C++?

There are three kinds of templates: function templates, class templates and, since C++14, variable templates. Since C++11, templates may be either variadic or non-variadic; in earlier versions of C++ they are always non-variadic.


1 Answers

The problem here is not the definition, but the declaration. You cannot inject a declaration in a namespace from a different namespace, so the specialization must be declared in the appropriate namespace before it can be defined in any enclosing namespace.

The definition of the base template can be done in the outer namespace because it has already been declared, so the code in the outer namespace provides a definition but does not inject any declaration into the namespace.

Try:

namespace ns {
    class foo
    {
        template <typename T> int bar (T *);
    };
    template <>
    int foo::bar<int>(int*); // declaration
}
template <typename T>
int ns :: foo :: bar (T*) {
    return 0;
}
template <>
int ns :: foo :: bar <int> (int *) {
    return 1;
}
like image 59
David Rodríguez - dribeas Avatar answered Oct 08 '22 17:10

David Rodríguez - dribeas