【发布时间】:2017-11-28 10:56:14
【问题描述】:
我无法弄清楚为什么代码无法编译,即使我有包含保护以防止重复编译
主类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 文件都编译了自己的函数。在这种情况下,如何正确定义模板专用函数?
【问题讨论】:
-
您将链接与编译混淆了。标头保护防止编译器(正在查看单个 cpp -> 对象转换)查找多个定义。链接器(需要多个对象 -> lib/exe)尝试将所有函数拼凑在一起。
-
是的,但是解决办法是什么?
-
旁白:为什么你的模板有两个具有相同主体的特化?如果有人拨打
Foo::Compare<3>会怎样? -
@Caleth,可以修改 Helper 中的 Compare 函数以提供默认行为,可能会引发错误。
-
@kstn 它可以,但两个版本都不是。为什么不只是一个免费功能
bool operator==(const Foo& this_foo, const Foo& other_foo);?