避免多次编译内联函数的定义
Avoid compiling definition of inline function multiple times
我在头文件中有一个非模板结构:
struct X {
constexpr X() : /* ... */ { /* ... */ }
constexpr void f() {
// ...
}
};
具有大小不等的功能。这用于很多不同的翻译单元,每个函数出现在多个目标文件中,以便它们在最终的可执行文件中被丢弃。
我想要的是将定义放在单个目标文件中,其他翻译单元可以内联函数或使用外部定义(类似于 C 中的 extern inline
语义)。我该怎么做?
它似乎适用于模板和 extern template
:
namespace detail {
template<std::nullptr_t>
struct X_base {
constexpr X_base() // ...
constexpr void f() // ...
};
extern template struct X_base<nullptr>;
}
struct X : detail::X_base<nullptr> {
using X_base::X_base;
};
// X.cpp
#include <X.hpp>
template struct detail::X_base<nullptr>;
但这是否有任何重大缺点(符号名称较长、难以阅读、需要文档等),或者是否有更简单的方法来做到这一点?
C++ 没有必须在一个翻译单元中 发出 并且因此肯定不需要在其他任何地方发出的内联函数的概念。 (它根本没有发出目标代码的概念,但关键是没有语法说“我保证这个定义对其他人来说是 ODR-identical 除了它而且只有它带有这个标记。”这样编译器 可以 做到这一点。)
但是,您想要的行为是实现 C++20 modules 的明显方式:因为已知模块中内联函数的定义是唯一的定义,它可以而且应该发出一次,以防多个导入翻译单元需要它的 out-of-line 副本。 (内联仍然是可能的,因为作为构建模块的一部分,定义以 compiler-internal 形式提供。)请记住,模块中 class 中定义的成员函数不会自动内联,尽管constexpr
仍然暗示它。
另一个丑陋的解决方法是使 non-inline wrappers 在常量计算之外使用,尽管如果有多个级别的 constexpr 函数可能会变得笨拙也可以在运行时使用。
我在头文件中有一个非模板结构:
struct X {
constexpr X() : /* ... */ { /* ... */ }
constexpr void f() {
// ...
}
};
具有大小不等的功能。这用于很多不同的翻译单元,每个函数出现在多个目标文件中,以便它们在最终的可执行文件中被丢弃。
我想要的是将定义放在单个目标文件中,其他翻译单元可以内联函数或使用外部定义(类似于 C 中的 extern inline
语义)。我该怎么做?
它似乎适用于模板和 extern template
:
namespace detail {
template<std::nullptr_t>
struct X_base {
constexpr X_base() // ...
constexpr void f() // ...
};
extern template struct X_base<nullptr>;
}
struct X : detail::X_base<nullptr> {
using X_base::X_base;
};
// X.cpp
#include <X.hpp>
template struct detail::X_base<nullptr>;
但这是否有任何重大缺点(符号名称较长、难以阅读、需要文档等),或者是否有更简单的方法来做到这一点?
C++ 没有必须在一个翻译单元中 发出 并且因此肯定不需要在其他任何地方发出的内联函数的概念。 (它根本没有发出目标代码的概念,但关键是没有语法说“我保证这个定义对其他人来说是 ODR-identical 除了它而且只有它带有这个标记。”这样编译器 可以 做到这一点。)
但是,您想要的行为是实现 C++20 modules 的明显方式:因为已知模块中内联函数的定义是唯一的定义,它可以而且应该发出一次,以防多个导入翻译单元需要它的 out-of-line 副本。 (内联仍然是可能的,因为作为构建模块的一部分,定义以 compiler-internal 形式提供。)请记住,模块中 class 中定义的成员函数不会自动内联,尽管constexpr
仍然暗示它。
另一个丑陋的解决方法是使 non-inline wrappers 在常量计算之外使用,尽管如果有多个级别的 constexpr 函数可能会变得笨拙也可以在运行时使用。