让我们说我有一个包含函数void foo();
的公共定义的库。库在内部调用此函数。为了获得最佳性能,我希望内联调用内联。我还想防止外部代码看到定义,以便以后我可以在不破坏ABI的情况下更改实现。这是一段代码:
MyLib.h:
void foo();
MyLibInlined.h:
inline void foo() { code here }
MyLib.cpp
#define inline
#include "MyLibInlined.h"
问题是它是否打破了ODR还是被视为不良做法?
修改
如果foo
是成员函数怎么办?
答案 0 :(得分:4)
问题是它是否打破了ODR还是被视为不良做法?
它不会破坏ODR,但会破坏[dcl.fct.spec]中的规则:
如果是具有外部链接的功能 在一个翻译单元中内联声明,应在其出现的所有翻译单元中内联声明; 无需诊断。
相反,您应该拥有该函数的公共版本,该函数未声明为内联版本,并且具有您在库中使用的内部版本:
// MyLibInlined.h
inline void foo_impl() { }
然后在库内定义foo
作为内部调用:
// MyLib.cpp
#include "MyLibInlined.h"
void foo() { foo_impl(); }
或者,如果对foo()
的所有调用都在一个文件中,您根本不需要担心,只需将其定义为非内联函数,并让编译器将其内联在文件中定义是可见的:
// MyLib.h
void foo();
// MyLib.cpp
void foo() { code here }
// use foo ...
inline
关键字并不意味着函数将被内联,这意味着定义是在标题中内联提供的。编译器不需要该关键字能够在定义它的文件中内联它,因为它可以看到定义。您只需inline
关键字即可让定义出现在多个翻译单元中,而不会导致多重定义错误。
答案 1 :(得分:0)
AFAIK确实打破了ODR,因为内联并不是一个规则,因为它是一个指导原则。尽管声明了这些函数,但允许编译器不内联函数。
另一方面,编译器也允许内联未声明的内联函数,并且可能在内部调用中对小函数执行此操作(在某些情况下,它可以在链接时执行),所以只需要&# 39;不用担心。
或者在单独的命名空间中声明内联版本,并使用内联命名空间在编译时解析它(或使用或其他)(http://en.cppreference.com/w/cpp/language/namespace#Inline_namespaces)
答案 2 :(得分:0)
基于此(C ++ 14 3.2 / 6)
似乎是非法的内联函数可以有多个定义 程序中的外部联系[...]提供了每个定义 出现在不同的翻译单元中,并且定义满足以下要求。特定 这样一个名为D的实体在多个翻译单元中定义,然后
[...]
- D的每个定义应由相同的令牌序列组成
第3.2节是关于一个定义规则的部分。
答案 3 :(得分:0)
这可能是你正在做的更清晰的变化:
// foo_pub.h -- public interface
#define foo() foo_pub()
void foo_pub();
// foo_private.h -- internal used by library
#define foo() foo_inline()
inline foo_inline() { ... }
// foo_pub.c -- definition for public function
void
foo_pub()
{
foo_inline()
}