2

I am using C++ 98. I am writing a JSON object wrapper. For all normal numbers, they can use the same function, but for floats and doubles, I need a seperate function. Same for strings. I wrote this using templates and specialization, and it compiles fine, but when I build my entire project I get about 1 billion errors about multiple definitions. I assume I am not specializing properly. I was able to compile this file with and without having these definitions within the class object itself, so I don't even know if those are required.

class Object {
    public:
        template <class T>
        bool Set(std::string key, T value);
        // having these defined or not doesn't seem to matter
        bool Set(std::string key, double value);
        bool Set(std::string key, float value);
        bool Set(std::string key, std::string value);
};


template <class T>
bool Object::Set(std::string key, T value){
}

template <>
bool Object::Set<double>(std::string key, double value){
}


template <>
bool Object::Set<float>(std::string key, float value){
}

template <>
bool Object::Set<std::string>(std::string key, std::string value){
}

How do I properly specialize these templates so that the compiler/linker doesn't have a fit?

user4581301
  • 33,082
  • 7
  • 33
  • 54
ony_pox232
  • 171
  • 1
  • 10
  • 2
    *I am using C++ 98*, dude we gotta get you off of that stuff. – user4581301 Aug 21 '20 at 19:42
  • Absolutely agree with @user4581301 Is this an actual constraint you have? If not, please use at least c++11, and even that's a decade old now. – cigien Aug 21 '20 at 19:43
  • Haha, of course it's an actual constraint. I have no choice in the matter. Call up WindRiver and ask them why it took 2 decades JUST to get to C++11.. – ony_pox232 Aug 21 '20 at 19:46
  • Fair enough, just checking. Often people end up using an old version because they had an old textbook or something. – cigien Aug 21 '20 at 19:47
  • 1
    To be honest, it's just a few years ago I dragged my company out of GCC 3.3 kicking and screaming the whole way. The new kids are enjoying the hell out of stuff like `std::thread` and lambdas. It's kinda nice to hear, "Omigod! This is as easy as Python!". Even if they're lying. – user4581301 Aug 21 '20 at 19:49
  • I can't tell you how much time having lambdas would have saved me. Actually I can, about 2-3 weeks. And of course there's a price on that to my company, too. Oh well. – ony_pox232 Aug 21 '20 at 19:50

1 Answers1

2

If you define specializations of a member function of a template outside the class in a header file, you need to make the specializations inline like this:

template <> 
inline bool Object::Set<double>(std::string key, double value){
}

template <>
inline bool Object::Set<float>(std::string key, float value){
}

template <>
inline bool Object::Set<std::string>(std::string key, std::string value){
}
cigien
  • 57,834
  • 11
  • 73
  • 112
  • Is this only true for specializations? – ony_pox232 Aug 21 '20 at 19:41
  • Yes, because specializations no longer rely on a template parameter, so they get instantiated for every header file they get included in. – cigien Aug 21 '20 at 19:42
  • Yikes. This will destroy my compile time and I am approaching a compiled file size limitation.. – ony_pox232 Aug 21 '20 at 19:43
  • 2
    If that's a concern, then there are ways around that. e.g. declaring the specializations in the header, and implementing them in a .cpp should help (I think). – cigien Aug 21 '20 at 19:45
  • That would be magical.. I will try that. However I am still a bit worried. This question has conflicting answers that say templates are always inline... https://stackoverflow.com/questions/10535667/does-it-make-any-sense-to-use-inline-keyword-with-templates – ony_pox232 Aug 21 '20 at 19:46
  • Well, templates are inline, but explicit specializations are not. Read the upvoted answer on the linked question closely, it's mentioned there :) – cigien Aug 21 '20 at 19:48