2

I found quite strange problem with template specialization.

Here: Type Traits - Explicit template specialization. fails on xcode

And here: C++ template specialization

It's written, that member function template specialization have to be out of class, but in same namespace (and yes, gcc 4.1.x version fails with errors if template specialization is inside class).

So, if I move member function template specialization below class, in same namespace, then msvc-2010 compiler thinks that I defined it twice: I have compiler error:

error LNK1169: one or more multiply defined symbols found

error LNK2005 with detail description of defining it twice.

If I move template specialization under same namespace into cpp file, then msvc-2010 don't see it, and fails with multiple errors when trying to use default template function for specialized parameters:

error C2678: binary '>>' : no operator found which takes a left-hand operand of type 'std::istringstream' (or there is no acceptable conversion)

(error happens because it tries to call operator >> to const char pointer)

So, msvc-2010 works for me just when template specialization is inside class, but then gcc-4.1.x not works.

Finally, where should I place template specialization, to be able to compile it in both compilers?

That's header:

#include <iostream>
#include <sstream>
#include <string>
class MyMap
{
public:
   template<typename T>
   T getValue(std::string phrase, T def)
   {
     std::istringstream ss(phrase);
     T ret;
     ss >> ret;
     if(ss.fail() || !ss.eof())
        return def;
     else
        return ret;
   }

And this specialization (from cpp, but I don't know where it have to be):

template<>
std::string  MyMap::getValue(std::string phrase, std::string def)    
{ 
   return phrase;
}
template<>
const char*  MyMap::getValue(std::string phrase, const char* def)    
{  
   return phrase.c_str();
}

Specialization for string and const char* (exactly to avoid ss >> ret; when ret is const char pointer).

Example is very simplified.

Community
  • 1
  • 1
Arkady
  • 2,084
  • 3
  • 27
  • 48

1 Answers1

5

You can put it in the header, outside the class definition like so:

template<>
inline std::string MyMap::getValue<std::string>(std::string phrase, std::string def)    
{ 
   return phrase;
}

template<>
inline const char* MyMap::getValue<const char*>(std::string phrase, const char* def)    
{  
   return phrase.c_str();
}

Or declare regular methods with the parameter set that you want it to have and define it in the .cpp as usual:

.h

class MyMap
{
    // ...
    std::string getValue(std::string phrase, std::string def);
    const char* getValue(std::string phrase, const char* def);
}

.cpp

std::string MyMap::getValue(std::string phrase, std::string def)    
{ 
   return phrase;
}

const char* MyMap::getValue(std::string phrase, const char* def)    
{  
   return phrase.c_str();
}
Patryk
  • 22,602
  • 44
  • 128
  • 244
  • `inline` keyword helps msvc-2010 pass it without duplication declaration errors, and gcc-4.1 works well with them outside of class. Thank you. – Arkady Feb 01 '16 at 10:47