RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1021524
Accepted
Трипольский Пётр
Трипольский Пётр
Asked:2020-09-09 01:06:56 +0000 UTC2020-09-09 01:06:56 +0000 UTC 2020-09-09 01:06:56 +0000 UTC

将 C++ 模板类与 CLang 编译器一起使用时的头文件

  • 772

编写了一个模板类,例如,从内联模板的类型推断 sizeof。

BaseInformer.h

template<typename ValueType>
class BaseInformer {
  private:
    int size;
  public:
    BaseInformer();
    virtual ~BaseInformer(){}
  public:
    virtual void printInfo();
    void printValue(ValueType value);
  public:
    std::string getSize() const;
    virtual std::string getName() const = 0;
};

extern template class BaseInformer<int>;
extern template class BaseInformer<char>;

BaseInformer.cpp

template class BaseInformer<int>;
template class BaseInformer<char>;

template<typename ReturnValue>
BaseInformer<ReturnValue>::BaseInformer() {
    size=sizeof(ReturnValue);
}

template<typename ValueType>
void BaseInformer<ValueType>::printValue(ValueType value) {
    std::cout << getName() << " " << value << "\n";
}

template<typename ValueType>
void BaseInformer<ValueType>::printInfo() {
    std::cout << getName() << " " << getSize() << "\n";
}

template<typename ValueType>
std::string BaseInformer<ValueType>::getSize() const {
    std::stringstream ss;
    ss << size;
    return ss.str();
}

类 IntInformer 和 CharInformer 继承自它并且具有几乎相同的内容:

IntInformer.h

class IntInformer : public BaseInformer<int> {
  public:
    IntInformer(){}
    virtual ~IntInformer() override {}
  public:
    virtual std::string getName() const override;
};

IntInformer.cpp

std::string IntInformer::getName() const {
    return "Int";
}

因此,下面是主要功能的部分

主文件

int main() {
    ...
    std::cout << "template printInfo()\n";
    IntInformer().printInfo();
    CharInformer().printInfo();
    ...
}

上面的代码使用MinGW64编译运行成功,使用MSVC2019x64编译器编译成功。但是,当尝试在 macOS 上使用 CLang 进行构建时,会输出以下日志:

Undefined symbols for architecture x86_64:
  "BaseInformer<char>::printValue(char)", referenced from:
      _main in main.o
  "BaseInformer<char>::printInfo()", referenced from:
      vtable for BaseInformer<char> in baseinformer.o
      vtable for CharInformer in charinformer.o
      _main in main.o
  "BaseInformer<char>::BaseInformer()", referenced from:
      CharInformer::CharInformer() in main.o
  "BaseInformer<int>::printValue(int)", referenced from:
      _main in main.o
  "BaseInformer<int>::printInfo()", referenced from:
      vtable for BaseInformer<int> in baseinformer.o
      vtable for IntInformer in intinformer.o
      _main in main.o
  "BaseInformer<int>::BaseInformer()", referenced from:
      IntInformer::IntInformer() in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [cpp-template-header] Error 1
20:02:57: Процесс «/usr/bin/make» завершился с кодом 2.

请告诉我,如果您想在不依赖于各种支持的编译器的情况下进行构建(在 CLang 下运行此业务),使用模板语法的正确方法是什么?如果可能的话,我想保留头文件和源代码文件的划分。为方便起见,我在此处发布了该项目。

c++
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-09-09T01:21:52Z2020-09-09T01:21:52Z

    模板的显式实例化的定义必须遵循模板本身的定义。

    类模板的显式实例化的定义也是其所有成员模板的显式实例化的定义。因此,类的显式实例化的定义通常应在其成员模板的定义之后指定。

    如果模板类的某些成员在整个类的显式实例化定义出现的时候没有被定义,那么它们就不会被显式实例化。见http://eel.is/c++draft/temp.explicit#12

    命名类模板特化的显式实例化定义显式地实例化类模板特化,并且是仅在实例化点已定义的那些成员的显式实例化定义。

    这正是您的案例中发生的情况:您的所有类方法都没有被显式实例化。因此,链接器没有找到它们。

    移动针迹

    template class BaseInformer<int>;
    template class BaseInformer<char>;
    

    到文件底部BaseInformer.cpp

    • 4

相关问题

  • C++ 和循环依赖

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    根据浏览器窗口的大小调整背景图案的大小

    • 2 个回答
  • Marko Smith

    理解for循环的执行逻辑

    • 1 个回答
  • Marko Smith

    复制动态数组时出错(C++)

    • 1 个回答
  • Marko Smith

    Or and If,elif,else 构造[重复]

    • 1 个回答
  • Marko Smith

    如何构建支持 x64 的 APK

    • 1 个回答
  • Marko Smith

    如何使按钮的输入宽度?

    • 2 个回答
  • Marko Smith

    如何显示对象变量的名称?

    • 3 个回答
  • Marko Smith

    如何循环一个函数?

    • 1 个回答
  • Marko Smith

    LOWORD 宏有什么作用?

    • 2 个回答
  • Marko Smith

    从字符串的开头删除直到并包括一个字符

    • 2 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5