c++ - (目标-)C++ 模板特化上的重复符号

标签 c++ xcode templates linker-errors objective-c++

好吧,从昨天开始我就一直在为这个奇怪的错误而苦苦挣扎,所以我想是时候问问社区了......

我目前正在使用 Objective-C++,我在头文件中有一个纯 C++ 类声明,如下所示:

#ifndef __MATRIX_H__
#define __MATRIX_H__

#define USE_NEON_UPSAMPLING2X true
#define USE_NEON_THRESHOLD true

typedef float OCRfloat;

template<class T = OCRfloat>
class Matrix {

public:
    ...

    Matrix threshold(T thresholdValue) const;

    ...

    Matrix upsample2x() const;

    ...
};

#ifdef TARGET_OS_IPHONE

#if USE_NEON_UPSAMPLING2X
template<> Matrix<float> Matrix<float>::upsample2x() const;
#endif

#if USE_NEON_THRESHOLD
template<> Matrix<float> Matrix<float>::threshold(float thresholdValue) const;
#endif

#endif

#include "Matrix.cpp"

#endif

它是模板类,具有基本的矩阵运算,但是,我想通过 T=float 上的模板特化来优化一些瓶颈。我有如下包含的 Matrix.cpp 文件:

#include <iostream>
#include <cmath>

#if defined TARGET_OS_IPHONE
#include <Accelerate/Accelerate.h>
#endif

...

template<class T> Matrix<T> Matrix<T>::threshold(T thresholdValue) const {
   ... // general naive algorithm
}

template<class T> Matrix<T> Matrix<T>::upsample2x() const{
   ... // general naive algorithm
}

#ifdef TARGET_OS_IPHONE

#if USE_NEON_UPSAMPLING2X
template<> Matrix<float> Matrix<float>::upsample2x() const{
   ... // specialized for ARM NEON float32_t
}
#endif

#if USE_NEON_THRESHOLD
template<> Matrix<float> Matrix<float>::threshold(float thresholdValue)const{
   ... // specialized for ARM NEON float32_t
}
#endif

问题如下: 如果我定义 USE_NEON_UPSAMPLING2X=false 和 USE_NEON_THRESHOLD=true,一切正常 - 应用程序已构建,并且运行良好。但是,如果我设置 USE_NEON_UPSAMPLING2X=true,链接器将中断并显示以下内容:

duplicate symbol __ZNK6MatrixIfE10upsample2xEv in:
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/B.o
duplicate symbol __ZNK6MatrixIfE10upsample2xEv in:
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/C.o
duplicate symbol __ZNK6MatrixIfE10upsample2xEv in:
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/A.o
    /.../OCRDemo-eggnlcolcwqycjagwvwddpfwgzlb/Build/Intermediates/OCRDemo.build/Release-iphoneos/OCRDemo.build/Objects-normal/armv7/D.o

有趣的是,这两种方法都在这些文件中使用,然而链接器只提示 upsample2x...两者之间的唯一区别,从句法的角度来看是参数的数量:阈值有一个参数T 的,而 upsample2x 不需要 - 除此之外,两者都定义为常量,都返回矩阵等。

所以我的问题是:是什么导致了这个神秘错误,我该如何解决?

最佳答案

你的错误是双重的。首先,您在 .cpp 文件中编写模板代码。然后,为了更正该错误,您将 .cpp 文件包含在 header 中,这是另一个坏主意。

为什么?

类模板并不是真正的类,只是一组类的模板。可以从中创建的类是根据需要创建的。另一方面,.cpp 文件仅编译一次,这还不够,甚至没有意义,因为此时您只有一个模板。

另一方面,包含 .cpp 文件本身就是一件坏事,因为它通常会导致重新编译可能无法重新编译的代码,从而导致链接错误。

编辑:您可以在 .cpp 文件中定义特化(但没有纯模板代码,并且不要包含它!),或者您可以内联它们并将它们保留在 header 中:

#if USE_NEON_UPSAMPLING2X
template<> inline Matrix<float> Matrix<float>::upsample2x() const{
   ... // specialized for ARM NEON float32_t
}
#endif

#if USE_NEON_THRESHOLD
template<> inline Matrix<float> Matrix<float>::threshold(float thresholdValue)const{
   ... // specialized for ARM NEON float32_t
}

关于c++ - (目标-)C++ 模板特化上的重复符号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18510703/

相关文章:

xcode - 如何在 Xcode 中显示光标当前的行和列位置?

c++ - 在模板参数中查找 typename 的 typename

c++ - 模板程序中的“模板前预期的主要表达式/';'”错误

c++ - 如何在头文件中声明类型转换并在cpp文件中实现?

ios - 当用户向右滑动以返回 View 时,您可以执行 prepareForSegue 吗?

c++ - 循环中的动态内存分配 - C++

xcode - 未找到 GeneratedInfoPlistDotEnv.h 文件

c++ - 仅接受某些类型的C++模板

c++ - 执行 AES 解密后字符串末尾的 Crypto++ 和垃圾

c++ - 特殊编译错误 : ‘cap’ does not name a type