我无法弄清楚为什么代码无法编译,即使我有防护重复编译的包含保护
主类foo.h:
#ifndef FOO_H_INCLUDED
#define FOO_H_INCLUDED
#include <iostream>
class Foo;
template<int TDim>
struct Foo_Helper
{
static bool Compare(const Foo& this_foo, const Foo& other_foo);
};
class Foo
{
public:
Foo(const int& Value) : mValue(Value) {}
virtual ~Foo() {}
const int& Value() const {return mValue;}
template<int TDim>
bool Compare(const Foo& rother_foo) {return Foo_Helper<TDim>::Compare(*this, rother_foo);}
private:
int mValue;
};
#endif
#include "foo.hpp"
foo.hpp定义模板特化:
#ifndef FOO_HPP_INCLUDED
#define FOO_HPP_INCLUDED
template<>
bool Foo_Helper<1>::Compare(const Foo& this_foo, const Foo& other_foo)
{
return this_foo.Value() == other_foo.Value();
}
template<>
bool Foo_Helper<2>::Compare(const Foo& this_foo, const Foo& other_foo)
{
return this_foo.Value() == other_foo.Value();
}
#endif
这两个源文件: src1.cpp:
#include "foo.h"
class Test1
{
public:
bool test()
{
Foo f1(1);
Foo f2(2);
return f1.Compare<1>(f2);
}
};
src2.cpp:
#include "foo.h"
class Test2
{
public:
bool test()
{
Foo f1(1);
Foo f2(2);
return f1.Compare<2>(f2);
}
};
的CMakeLists.txt:
set(file_list
src1.cpp
src2.cpp
)
add_library(Test SHARED ${file_list})
错误消息:
Linking CXX shared library libTest.so
CMakeFiles/Test.dir/src2.cpp.o: In function `Foo_Helper<1>::Compare(Foo const&, Foo const&)':
/home/hbui/workspace/c++/multiple_definition_error/foo.hpp:7: multiple definition of `Foo_Helper<1>::Compare(Foo const&, Foo const&)'
CMakeFiles/Test.dir/src1.cpp.o:/home/hbui/workspace/c++/multiple_definition_error/foo.hpp:7: first defined here
CMakeFiles/Test.dir/src2.cpp.o: In function `Foo_Helper<2>::Compare(Foo const&, Foo const&)':
/home/hbui/workspace/c++/multiple_definition_error/foo.hpp:13: multiple definition of `Foo_Helper<2>::Compare(Foo const&, Foo const&)'
CMakeFiles/Test.dir/src1.cpp.o:/home/hbui/workspace/c++/multiple_definition_error/foo.hpp:13: first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [multiple_definition_error/libTest.so] Error 1
make[1]: *** [multiple_definition_error/CMakeFiles/Test.dir/all] Error 2
make: *** [all] Error 2
我认为包含守护已经阻止了foo.hpp中的两个函数被编译。但是,看起来每个cpp文件都编译自己的函数。在这种情况下,如何正确定义模板专用函数?
答案 0 :(得分:2)
标题保护会停止在同一翻译单元中包含两次的标题。您的问题是Compare
专精的定义将在两个翻译单元中定义,但不会标记为inline
。这意味着当链接器尝试链接test1.cpp和test2.cpp生成的目标文件时,它会给出多重定义错误。如果您将特化标记为inline
,那么它们可以在两个TU中定义,链接器将丢弃其中一个定义:
template<>
inline bool Foo_Helper<1>::Compare(const Foo& this_foo, const Foo& other_foo)
//^^^^
{
return this_foo.Value() == other_foo.Value();
}
template<>
inline bool Foo_Helper<2>::Compare(const Foo& this_foo, const Foo& other_foo)
//^^^^
{
return this_foo.Value() == other_foo.Value();
}