“……的多重定义”模板函数的完全特化的错误
我有一个配置项目:
./main.cpp
./type_traints/TypeTraints.cpp
./type_traints/TypeTraints.hpp
./type_traints/chapter_20.hpp
./type_traints/CMakeLists.txt 文件是:
cmake_minimum_required (VERSION 2.8)
add_library(chapter_20 TypeTraints.cpp)
./CMakeLists.txt 如下:
cmake_minimum_required (VERSION 2.8)
project (mpl)
add_subdirectory(type_traints)
include_directories(type_traints)
link_directories(type_traints)
add_executable (mpl main.cpp)
target_link_libraries(mpl chapter_20)
文件的相关部分(大部分包含省略)包括:
./type_traints/chapter_20.hpp
#ifndef CHAPTER_20_GUARD
#define CHAPTER_20_GUARD
#include <TypeTraints.hpp>
void chapter_20() {
test_23();
}
#endif //CHAPTER_20_GUARD
./type_traints/TypeTraints.hpp
#ifndef TYPE_TRAINTS_GUARD
#define TYPE_TRAINTS_GUARD
namespace details {
template<class T> const char* class2name() {
return "unknown";
};
template<> const char* class2name<int>() {
return "int";
};
}
template<class T>
class type_descriptor {
friend std::ostream& operator << (std::ostream& stream,
const type_descriptor<T>& desc) {
stream << desc.getName();
return stream;
}
public:
std::string getName() const;
};
template<class T>
std::string type_descriptor<T>::getName() const {
return details::class2name<T>();
}
void test_23();
#endif // TYPE_TRAINTS_GUARD
./type_traints/TypeTraints.cpp
#include<TypeTraints.hpp>
void test_23() {
cout << type_descriptor<int>() << endl;
}
和 ./main.cpp
#include <chapter_20.hpp>
int main(int argc, char* argv[]) {
chapter_20();
return 0;
}
项目编译但无法链接:
[ 50%] Building CXX object type_traints/CMakeFiles/chapter_20.dir/TypeTraints.cpp.o
Linking CXX static library libchapter_20.a
[ 50%] Built target chapter_20
[100%] Building CXX object CMakeFiles/mpl.dir/main.cpp.o
Linking CXX executable mpl
type_traints/libchapter_20.a(TypeTraints.cpp.o): In function `char const* details::cl
ass2name<int>()':
/home/marcin/Projects/mpl/type_traints/TypeTraints.hpp:312: multiple definition of `c
har const* details::class2name<int>()'
CMakeFiles/mpl.dir/main.cpp.o:/home/marcin/Projects/mpl/type_traints/TypeTraints.hpp:
312: first defined here
collect2: ld returned 1 exit status
make[2]: *** [mpl] Błąd 1
make[1]: *** [CMakeFiles/mpl.dir/all] Error 2
make: *** [all] Error 2
23:56:20@marcin-laptop ~/P
如果我删除 class2name 专业化 (class2name< ;int>()
) 来自 TypeTraints.hpp 并仅使用通用实现。
有人知道这是为什么吗?我是否错过配置 cmake 文件?
I have a project with configuration:
./main.cpp
./type_traints/TypeTraints.cpp
./type_traints/TypeTraints.hpp
./type_traints/chapter_20.hpp
The ./type_traints/CMakeLists.txt file is:
cmake_minimum_required (VERSION 2.8)
add_library(chapter_20 TypeTraints.cpp)
and the ./CMakeLists.txt follows:
cmake_minimum_required (VERSION 2.8)
project (mpl)
add_subdirectory(type_traints)
include_directories(type_traints)
link_directories(type_traints)
add_executable (mpl main.cpp)
target_link_libraries(mpl chapter_20)
Relevant parts of files (most includes omitted) include:
./type_traints/chapter_20.hpp
#ifndef CHAPTER_20_GUARD
#define CHAPTER_20_GUARD
#include <TypeTraints.hpp>
void chapter_20() {
test_23();
}
#endif //CHAPTER_20_GUARD
./type_traints/TypeTraints.hpp
#ifndef TYPE_TRAINTS_GUARD
#define TYPE_TRAINTS_GUARD
namespace details {
template<class T> const char* class2name() {
return "unknown";
};
template<> const char* class2name<int>() {
return "int";
};
}
template<class T>
class type_descriptor {
friend std::ostream& operator << (std::ostream& stream,
const type_descriptor<T>& desc) {
stream << desc.getName();
return stream;
}
public:
std::string getName() const;
};
template<class T>
std::string type_descriptor<T>::getName() const {
return details::class2name<T>();
}
void test_23();
#endif // TYPE_TRAINTS_GUARD
./type_traints/TypeTraints.cpp
#include<TypeTraints.hpp>
void test_23() {
cout << type_descriptor<int>() << endl;
}
and ./main.cpp
#include <chapter_20.hpp>
int main(int argc, char* argv[]) {
chapter_20();
return 0;
}
The project compiles but fails to link:
[ 50%] Building CXX object type_traints/CMakeFiles/chapter_20.dir/TypeTraints.cpp.o
Linking CXX static library libchapter_20.a
[ 50%] Built target chapter_20
[100%] Building CXX object CMakeFiles/mpl.dir/main.cpp.o
Linking CXX executable mpl
type_traints/libchapter_20.a(TypeTraints.cpp.o): In function `char const* details::cl
ass2name<int>()':
/home/marcin/Projects/mpl/type_traints/TypeTraints.hpp:312: multiple definition of `c
har const* details::class2name<int>()'
CMakeFiles/mpl.dir/main.cpp.o:/home/marcin/Projects/mpl/type_traints/TypeTraints.hpp:
312: first defined here
collect2: ld returned 1 exit status
make[2]: *** [mpl] Błąd 1
make[1]: *** [CMakeFiles/mpl.dir/all] Error 2
make: *** [all] Error 2
23:56:20@marcin-laptop ~/P
The project links fine if I remove the class2name specialization (class2name<int>()
) from TypeTraints.hpp and use only the generic implementation.
Does anybody have an idea Why is that? Did I miss-configure cmake files?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
简而言之:显式(即完全)专用的模板函数不再是模板。它是一个普通函数,并且遵循普通函数的单一定义规则。
换句话说,您无法在头文件中明确定义专用函数模板。这样做会导致 ODR 违规。
只要模板至少依赖于一个参数,它就是模板。即部分特化可以在头文件中定义(因为它们仍然模板)。 显式(即完整)特化只能在头文件中声明,但必须在实现文件中定义,就像普通函数一样。
In short: an explicitly (i.e. fully) specialized template function is no longer a template. It is an ordinary function and it obeys One Definition Rule for ordinary functions.
In other words you can't define explicitly specialized function templates in header file. Doing so will result in ODR violations.
A template is a template only as long as it depends on at least one parameter. I.e. partial specializations can be defined in header files (since they are still templates). Explicit (i.e. full) specializations can only be declared in header files, but have to be defined in implementation files, just like ordinary functions.
这违反了单一定义规则:
class2name
模板函数的显式特化不属于这些情况。因此,我相信将 class2nameThis is a violation of the one definition rule :
An explicit specialization of the
class2name
template function does not fall in any of these cases. For this reason, I believe that movingclass2name<int>()
definition into an implementation file should fix the issue. I also think you should have a look on "Why not specialize function templates ?".您的文件:
其中 TypeTraints.hpp 直接包含在 TypeTraits.cpp 中,间接包含在 main.cpp 中(通过 Chapter_20.hpp)。但是,您的完整规范模板
是在 TypeTraints.hpp 中定义的,它存在于两个不同的编译单元(上面的两个 .cpp 文件)中。这两个文件在编译后会链接在一起,这会导致多重定义链接错误。
Your files:
in which TypeTraints.hpp is directly included in TypeTraits.cpp and indirectly included in main.cpp(through chapter_20.hpp). However, you fully specification template
is defined in TypeTraints.hpp which be existing in two different compilation units(the above two .cpp file). These two files will be linked together after compilation and this cause the multiple definition link error.