Template specialization doesn't work after putting inside a namespace

T

tharinda.gl

Hi all,
I had a class with template methods and I have used
template specialization to handle special cases. But now the compiler
gives me errors after putting that class inside a namespace. What
should be done to get rid of this error?

This works

class A
{
template<typename T> MyFunc(T){}
template<> MyFunc<A*> MyFunc(A*){}
};

But this doesn't

namespace B
{
class A
{
template<typename T> MyFunc(T){}
template<> MyFunc<A*> MyFunc(A*){}
};
};


Thanks in Advance!

Tharinda
 
T

tharinda.gl

Hi all,
           I had a class with template methods and I have used
template specialization to handle special cases. But now the compiler
gives me errors after putting that class inside a namespace. What
should be done to get rid of this error?

This works

class A
{
       template<typename T> MyFunc(T){}
       template<> MyFunc<A*> MyFunc(A*){}

};

But this doesn't

namespace B
{
     class A
     {
            template<typename T> MyFunc(T){}
            template<> MyFunc<A*> MyFunc(A*){}
     };

};

Thanks in Advance!

Tharinda

I am using gcc version 3.4.3
 
A

Andrey Tarasevich

This works

class A
{
template<typename T> MyFunc(T){}
template<> MyFunc<A*> MyFunc(A*){}
};

But this doesn't

namespace B
{
class A
{
template<typename T> MyFunc(T){}
template<> MyFunc<A*> MyFunc(A*){}
};
};

Neither works. In both cases the first declaration doesn't specify
return type for a function, which is illegal in C++. Both variants are
ill-formed. Post real code.
 
T

Triple-DES

Hi all,
           I had a class with template methods and I have used
template specialization to handle special cases. But now the compiler
gives me errors after putting that class inside a namespace. What
should be done to get rid of this error?

This works

class A
{
       template<typename T> MyFunc(T){}
       template<> MyFunc<A*> MyFunc(A*){}

};

But this doesn't

namespace B
{
     class A
     {
            template<typename T> MyFunc(T){}
            template<> MyFunc<A*> MyFunc(A*){}
     };

};

There are quite a few trivial errors in the code you have posted.
Possibly you intented to write something like this:

class A
{
template<typename T> void MyFunc(T) {} // OK
};
template<> void A::MyFunc<A*>(A*) {} // OK

namespace B
{
class A
{
template<typename T> void MyFunc(T) {} // OK
};
template<> void A::MyFunc<A*>(A*) {} //OK
}

As you can see, the namespace should make no difference, but you have
to place your specializations outside the class, OR simply use
overloading instead, like this:
class A
{
template<typename T> void MyFunc(T) {} // OK
void MyFunc(A*) {} // OK
};
 
T

tharinda.gl

Neither works. In both cases the first declaration doesn't specify
return type for a function, which is illegal in C++. Both variants are
ill-formed. Post real code.

Sorry Real Code was too big to be posted here. I am putting a
compilable code below

// This works

#include <iostream>

class A
{
public:
template<typename T> void PrintValue(T val);
};

template<typename T> void A::printValue(T val)
{
std::cout << "Primary Method " << val << std::endl;
}

template<> void A::printValue<double>(double dVal)
{
std::cout << "Specialized Method " << dVal << std::endl;
}

int main(int argc, char* argv[])
{
A objA;

objA.PrintValue<int>(5);
objA.PrintValue<double>(10.50);

return 0;
}

//This doesn't

#include <iostream>

namespace NS
{
class A
{
public:
template<typename T> void PrintValue(T val);
};
};

template<typename T> void NS::A::printValue(T val)
{
std::cout << "Primary Method " << val << std::endl;
}

template<> void NS::A::printValue<double>(double dVal)
{
std::cout << "Specialized Method " << dVal << std::endl;
}

int main(int argc, char* argv[])
{
NS::A objA;

objA.PrintValue<int>(5);
objA.PrintValue<double>(10.50);

return 0;
}

//These are the errors given by the compiler (gcc 3.4.3)

g++ Test.cpp
Test.cpp:19: error: specialization of `template<class T> void
NS::A::printValue(T)' in different namespace
Test.cpp:9: error: from definition of `template<class T> void
NS::A::printValue(T)'
Test.cpp:20: confused by earlier errors, bailing out

Thanks!

Tharinda
 
A

Andrey Tarasevich

//This doesn't

#include <iostream>

namespace NS
{
class A
{
public:
template<typename T> void PrintValue(T val);
};
};

}

Namespace definitions don't end with ';'.
template<typename T> void NS::A::printValue(T val)
{
std::cout << "Primary Method " << val << std::endl;
}

template<> void NS::A::printValue<double>(double dVal)
{
std::cout << "Specialized Method " << dVal << std::endl;
}

int main(int argc, char* argv[])
{
NS::A objA;

objA.PrintValue<int>(5);
objA.PrintValue<double>(10.50);

return 0;
}

//These are the errors given by the compiler (gcc 3.4.3)

g++ Test.cpp
Test.cpp:19: error: specialization of `template<class T> void
NS::A::printValue(T)' in different namespace
Test.cpp:9: error: from definition of `template<class T> void
NS::A::printValue(T)'
Test.cpp:20: confused by earlier errors, bailing out

The specialization for a member function template must be _declared_ in
the same namespace as the class itself (see 14.7.3/2). This means that
if you want to move the _definition_ of the member function template
somewhere else, you have to at least leave a _declaration_ inside the
namespace. In this code you violate this requirement: you are not
declaring the specialization of 'A::printValue<double>' inside the NS
namespace first.

In order to make the code compilable, add the declaration for the
specialization to the namespace

namespace NS
{
class A
{
public:
template<typename T> void PrintValue(T val);
};

template<> void A::printValue<double>(double dval); // <- added
}

template<typename T> void NS::A::printValue(T val)
{
// ...
}

template<> void NS::A::printValue<double>(double dVal)
{
// ...
}

In your first example (without namespace) class 'A' was a member of
global namespace. You _defined_ the specialization of
'A::printValue<double>' in global namespace as well. In that case the
definition served as declaration at the same time, so the above
requirement was naturally met.

So, alternatively, you can follow the same structure to make the code
with namespace NS compilable. In order to do that you have to move the
function definitions into the namespace

namespace NS
{
class A
{
public:
template<typename T> void PrintValue(T val);
};

template<typename T> void A::printValue(T val)
{
// ...
}

template<> void A::printValue<double>(double dVal)
{
// ...
}
}

This will also compile.
 
T

tharinda.gl

//This doesn't
#include <iostream>
namespace NS
{
   class A
   {
   public:
           template<typename T> void PrintValue(T val);
   };
};

   }

Namespace definitions don't end with ';'.


template<typename T> void NS::A::printValue(T val)
{
   std::cout << "Primary Method " << val << std::endl;
}
template<> void NS::A::printValue<double>(double dVal)
{
   std::cout << "Specialized Method " << dVal << std::endl;
}
int main(int argc, char* argv[])
{
   NS::A objA;
   objA.PrintValue<int>(5);
   objA.PrintValue<double>(10.50);
   return 0;
}
//These are the errors given by the compiler (gcc 3.4.3)
g++ Test.cpp
Test.cpp:19: error: specialization of `template<class T> void
NS::A::printValue(T)' in different namespace
Test.cpp:9: error:   from definition of `template<class T> void
NS::A::printValue(T)'
Test.cpp:20: confused by earlier errors, bailing out

The specialization for a member function template must be _declared_ in
the same namespace as the class itself (see 14.7.3/2). This means that
if you want to move the _definition_ of the member function template
somewhere else, you have to at least leave a _declaration_ inside the
namespace. In this code you violate this requirement: you are not
declaring the specialization of 'A::printValue<double>' inside the NS
namespace first.

In order to make the code compilable, add the declaration for the
specialization to the namespace

   namespace NS
   {
     class A
     {
     public:
       template<typename T> void PrintValue(T val);
     };

     template<> void A::printValue<double>(double dval); // <- added
   }

   template<typename T> void NS::A::printValue(T val)
   {
     // ...
   }

   template<> void NS::A::printValue<double>(double dVal)
   {
     // ...
   }

In your first example (without namespace) class 'A' was a member of
global namespace. You _defined_ the specialization of
'A::printValue<double>' in global namespace as well. In that case the
definition served as declaration at the same time, so the above
requirement was naturally met.

So, alternatively, you can follow the same structure to make the code
with namespace NS compilable. In order to do that you have to move the
function definitions into the namespace

   namespace NS
   {
     class A
     {
     public:
       template<typename T> void PrintValue(T val);
     };

     template<typename T> void A::printValue(T val)
     {
       // ...
     }

     template<> void A::printValue<double>(double dVal)
     {
       // ...
     }
   }

This will also compile.

Thank you very much Andrey, you have clarified all my doubts

Regards,
Tharinda
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top