2010-12-20 112 views
2


我有一个配置的项目:“的......多重定义”错误

./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如下:FIL的

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) 

相关部分ES(最包括略)包括:
./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; 
} 

该项目编译,但无法链接:如果我从TypeTraints.hpp删除class2name专业化(class2name<int>()),并且只使用了通用实现

[ 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:[email protected] ~/P 

项目链接罚款。

有没有人有想法为什么?我错过了配置cmake文件吗?

回答

9

简而言之:明确(即完全)专用的模板函数不再是模板。它是一个普通的功能,它遵循普通函数的一个定义规则。

换句话说,你不能在头文件中定义明确的专用函数模板。这样做会导致违反ODR。

模板只有在至少取决于一个参数的情况下才是模板。即部分专业化可以是在头文件中定义(因为它们仍然是模板)。 明确的(即完整)专业化只能在头文件中声明,但必须在实现文件中定义,就像普通函数一样。

+0

谢谢你的回答。但是,将函数定义更改为TypeTraints.cpp(template <> const char * class2name (){return“int”}中的声明(模板<> const char * class2name ();)一个compilatin错误:“/home/marcin/Projects/mpl/type_traints/TypeTraints.cpp:120:error:expected initializer before'<'token” – Marcin 2010-12-21 00:08:00

+0

@Marcin:你搞砸了一些东西。 。我猜你忘了命名空间,该定义应该在'details'命名空间内完成,或者应该使用一个限定名称(即它必须明确声明它是'details:class2name '你是定义) – AnT 2010-12-21 00:24:55

+0

是的,我已经搞砸了命名空间,一个试过的程序员是个笨手笨脚的程序员:/谢谢你,你太棒了! – Marcin 2010-12-21 00:28:57

3

这是一个定义规则的违反:

There can be more than one definition of a class type (clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (clause 14), non-static function template (14.5.5), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.4) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements.

class2name模板功能的明确分工不属于任何一种情况下。出于这个原因,我认为将class2name<int>()定义移动到实现文件中可以解决问题。我也认为你应该看看"Why not specialize function templates ?"

+0

我知道模板功能专业化的弊端 - 这只是一个教育练习 – Marcin 2010-12-21 00:10:00

1

你的文件:

./main.cpp 
./type_traints/TypeTraints.cpp 
./type_traints/TypeTraints.hpp 
./type_traints/chapter_20.hpp 

其中TypeTraints.hpp被直接包括在TypeTraits.cpp和间接包括在main.cpp中(通过chapter_20.hpp)。不过,你完全规范模板

template<> const char* class2name<int>() { 
    return "int"; 
}; 

在TypeTraints.hpp这两个不同的编译单元(上述两个.cpp文件)将现有的定义。这两个文件将在编译后链接到一起,这会导致多重定义链接错误。

+1

想知道,为什么不包括多重defini在这种情况下tions? – Azmisov 2016-11-23 22:00:22