0

I'm using EnumParser from here It compiles fine in VC++, but using gcc I have such error:

./Terminator.o: In function `EnumParser<FieldType>::EnumParser()':
Terminator.cpp:(.text+0x960): multiple definition of `EnumParser<FieldType>::EnumParser()'
./MicexGate.o:MicexGate.cpp:(.text+0xd0): first defined here
./Terminator.o: In function `EnumParser<FieldType>::EnumParser()':
Terminator.cpp:(.text+0x960): multiple definition of `EnumParser<FieldType>::EnumParser()'
./MicexGate.o:MicexGate.cpp:(.text+0xd0): first defined here
./Terminator.o: In function `EnumParser<FieldsetName>::EnumParser()':

It seems EnumParser<FieldType>::EnumParser() appeared in both MicexGate.o and Terminator.o and this is the problem. But i don't know why this is an error and how to fix it.

In my program I define this EnumParser just once in .cpp file in MicexGate static lib project. Terminator depends on MicexGate probably that's why finally EnumParser defined twice. This is how I define EnumParser<FieldType>:

#include "FieldsConverter.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include "ByteArrayReader.h"
#include "Utils.h"
#include "CommonsMicexBridge.h"
#include "InstrumentsStorage.h"
#include <boost/algorithm/string.hpp>

template<> EnumParser<FieldType>::EnumParser()
{
    enumMap["Char"] = Char;
    enumMap["Integer"] = Integer;
    enumMap["Long"] = Long;
    enumMap["Fixed"] = Fixed;
    enumMap["Price"] = Price;
    enumMap["Date"] = Date;
    enumMap["Time"] = Time;
}

How can I fix my problem?

Community
  • 1
  • 1
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • 1
    Have you declared the explicit specialisation, and included that declaration in every file that uses it? If the compiler doesn't know about it, then it will specialise the generic template instead of using your specialisation, resulting in multiple definitions. – Mike Seymour Sep 22 '14 at 12:26

2 Answers2

1

Templates need to be in headers and not in .cpp files.

murrekatt
  • 5,961
  • 5
  • 39
  • 63
  • 1
    While true, it doesn't explain the errors the OP is asking about. – Some programmer dude Sep 22 '14 at 12:15
  • 1
    This is an explicit specialisation, not a template definition. It's subject to the One Definition Rule just like a regular function; so does need to either go in a source file, or be declared `inline`. – Mike Seymour Sep 22 '14 at 12:21
  • it was originally in `.h` file but I was having same compilation error. I moved it to .cpp, hope this can help, but it doesn't – Oleg Vazhnev Sep 22 '14 at 12:30
  • @javapowered: If it's in a header, then it needs to be `inline`. If it's in a source file, then it needs a declaration in a header. – Mike Seymour Sep 22 '14 at 13:15
1

My guess is that you haven't declared the explicit specialisation in a header, included in every file that uses the specialisation:

template<> EnumParser<FieldType>::EnumParser();

Without this declaration, the compiler doesn't know that the explicit specialisation exists, so will instantiate an implicit specialisation from the generic template if it needs one. You now have two definitions, resulting (hopefully) in a link error.

Alternatively, as with any function, you can define it in a header as long as you declare it inline to allow definitions in multiple translation unit.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • i've tried to move to .h file and to add `inline` but this doesn't help. i will try to add explicit declaration to .h file and implementation to .cpp – Oleg Vazhnev Sep 22 '14 at 13:42
  • i've tried to sepate: definition in .h file implementation in .cpp file. This doesn't work too in my case by some reason. – Oleg Vazhnev Sep 22 '14 at 13:55
  • @javapowered: Do you mean you tried with a *declaration* in `.h` file (as in my answer) and *definition* (aka impelementation) in `.cpp` file (as in your question)? That should work, as long as you include the header wherever the specialisation is needed. If not, please show us what you tried (preferably as a minimal, but complete, test case) and what went wrong. – Mike Seymour Sep 22 '14 at 14:14
  • thanks, i don't know what happened first time, i've tried several more times, moved to another .h files and after all it works. sometimes just adding `inline` in `.h` is enough, thanks again! – Oleg Vazhnev Sep 22 '14 at 14:40