Partially specialized template inherited by normal class. (multiple definition of ...)

Hello everyone. This is my first post on this forum.
I have a huge problem with inheritance a partially specialized class (one method depends on type). My code looks ok, but something not working. Please help. This is very rare situation and i cannot find answer.
My template code (helpers/helperdataarray.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#ifndef HELPERDATAARRAY_H
#define HELPERDATAARRAY_H

#include "colladafile_global.h"
#include "helperelement.h"
#include "helperidandname.h"
#include "daesimpletypes.h"
#include <QStringList>

namespace daehelpers
{
template <typename T> class COLLADAFILESHARED_EXPORT HelperDataArray :
        public virtual HelperElement,
        public virtual HelperIDAndName
{
public:
    HelperDataArray() :
        _count(0),
        _value_(0) { }
    virtual ~HelperDataArray()
    {
        if(_value_) delete [] _value_;
    }
    void Parse()
    {
        HelperIDAndName::Parse();

        if(!Value_())
        {
            _count = Element().attribute("count").toUInt();
            if(Count())
            {
                QStringList strList = Element().text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
                if((unsigned int)strList.count() != Count())
                {
                    _count = 0; return;
                    // to throw exception -> count mismatch
                }
                ParseDataArray(strList);
            }
        }
    }
    DAEUIntType Count()
    {
        return _count;
    }
    T *Value_()
    {
        return _value_;
    }

protected:
    DAEUIntType _count;

    T *_value_;

private:
    void ParseDataArray(const QStringList &strList);
};
}

/******************************************************************************
 * Implementation / Specialization                                            *
 ******************************************************************************/

namespace daehelpers
{
template <typename T> void HelperDataArray<T>::ParseDataArray(const QStringList &strList)
{
    _count = 0;
    // does almost nothing except reset the counter -> not supported data array
    // possibly can throw some kind of an exception
}

template <> void HelperDataArray<bool>::ParseDataArray(const QStringList &strList)
{
    _value_ = new bool [Count()];
    unsigned int i = 0;
    foreach(QString str, strList)
        _value_[i ++] = (str.toLower() == "true" || str == "1");
}

template <> void HelperDataArray<float>::ParseDataArray(const QStringList &strList)
{
    _value_ = new float [Count()];
    unsigned int i = 0; bool ok;
    foreach(QString str, strList)
    {
        _value_[i ++] = str.toFloat(&ok);
        if(!ok)
        {
            delete [] _value_;
            _value_ = 0;
            _count = 0;
            // possibly can throw some kind of an exception about wrong parsing
        }
    }
}

template <> void HelperDataArray<int>::ParseDataArray(const QStringList &strList)
{
    _value_ = new int [Count()];
    unsigned int i = 0; bool ok;
    foreach(QString str, strList)
    {
        _value_[i ++] = str.toInt(&ok);
        if(!ok)
        {
            delete [] _value_;
            _value_ = 0;
            _count = 0;
            // possibly can throw some kind of an exception about wrong parsing
        }
    }
}

template <> void HelperDataArray<QString>::ParseDataArray(const QStringList &strList)
{
    _value_ = new QString [Count()];
    unsigned int i = 0;
    foreach(QString str, strList)
        _value_[i ++] = str;
}
}

#endif // HELPERDATAARRAY_H 

My first class code (daeboolarray.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#ifndef DAEBOOLARRAY_H
#define DAEBOOLARRAY_H

#include "colladafile_global.h"
#include "helpers/helperelement.h"
#include "helpers/helperdataarray.h"

class COLLADAFILESHARED_EXPORT DAEBoolArray :
        public virtual daehelpers::HelperElement,
        public virtual daehelpers::HelperDataArray<bool>
{
public:
    DAEBoolArray() { }
    DAEBoolArray(const QDomElement &element) :
        HelperElement(element) { }
    ~DAEBoolArray() { }
    void Parse()
    { daehelpers::HelperDataArray<bool>::Parse(); }
};

#endif // DAEBOOLARRAY_H 

My second class code (daeintarray.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef DAEINTARRAY_H
#define DAEINTARRAY_H

#include "colladafile_global.h"
#include "helpers/helperelement.h"
#include "helpers/helperdataarray.h"

class COLLADAFILESHARED_EXPORT DAEIntArray :
        public virtual daehelpers::HelperElement,
        public virtual daehelpers::HelperDataArray<int>
{
public:
    DAEIntArray() :
        _minInclusive(-2147483647 - 1),
        _maxInclusive(2147483647) { }
    DAEIntArray(const QDomElement &element) :
        HelperElement(element),
        _minInclusive(-2147483647 - 1),
        _maxInclusive(2147483647) { }
    ~DAEIntArray() { }
    void Parse()
    {
        daehelpers::HelperDataArray<int>::Parse();
    }
    DAEInteger MinInclusive()
    {
        return _minInclusive;
    }
    DAEInteger MaxInclusive()
    {
        return _maxInclusive;
    }

private:
    DAEInteger _minInclusive;
    DAEInteger _maxInclusive;
};

#endif // DAEINTARRAY_H 

Some compile errors:

./release/colladafile.o:colladafile.cpp:(.text+0x2c): multiple definition of `daehelpers::HelperDataArray<float>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x2b0): first defined here
./release/colladafile.o:colladafile.cpp:(.text+0x618): multiple definition of `daehelpers::HelperDataArray<QString>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x458): first defined here
./release/colladafile.o:colladafile.cpp:(.text+0x7c0): multiple definition of `daehelpers::HelperDataArray<int>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0xfc): first defined here
./release/colladafile.o:colladafile.cpp:(.text+0x974): multiple definition of `daehelpers::HelperDataArray<bool>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x600): first defined here
./release/daegeometry.o:daegeometry.cpp:(.text+0x7c0): multiple definition of `daehelpers::HelperDataArray<QString>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x458): first defined here
./release/daegeometry.o:daegeometry.cpp:(.text+0x968): multiple definition of `daehelpers::HelperDataArray<int>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0xfc): first defined here
./release/daegeometry.o:daegeometry.cpp:(.text+0xb1c): multiple definition of `daehelpers::HelperDataArray<float>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x2b0): first defined here
./release/daegeometry.o:daegeometry.cpp:(.text+0xcc4): multiple definition of `daehelpers::HelperDataArray<bool>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x600): first defined here
./release/daefile.o:daefile.cpp:(.text+0x154): multiple definition of `daehelpers::HelperDataArray<bool>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x600): first defined here
./release/daefile.o:daefile.cpp:(.text+0x480): multiple definition of `daehelpers::HelperDataArray<QString>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0x458): first defined here
./release/daefile.o:daefile.cpp:(.text+0x628): multiple definition of `daehelpers::HelperDataArray<int>::ParseDataArray(QStringList const&)'
./release/helpersource_core.o:helpersource_core.cpp:(.text+0xfc): first defined here
...


Sorry for long listings but maybe problem lies elsewhere and additional code can be usefull to understand.
Last edited on
The reason this comes up, is that linker thinks, that the same functions have been implemented multiple times. But you implemented the functions that created the errors only once in the header file. Each header file is compiled every time it is included. Therefore the specialized functions are compiled multiple times and the linker complains.

Therefore, the solution to your problem is: Put the implementations of the template specializations into the cpp files. You can declare a specialization if you want to so for clarity. But you don't need to do so.

Was that clear? Or was that too complicated?
Your answer is very clear for me, thank you for quick reply. I was almost sure that I did so earlier, but maybe I've put whole implementation of template to *.cpp file (what is wrong what I've learned). For two years without a C++ is a lot to forget. Thanks alot.
Topic archived. No new replies allowed.