c++ - 有条件地添加到重载集是否合法

标签 c++ language-lawyer

考虑我们有接受一些基本类型的函数:

void print(const base&);

然后,我们在另一个 header 中定义了一个继承自 base 的结构,称之为 derived。最后,在第三个 header 中,我们有一个 print 的重载,它接受一个 derived。总的来说,我们有这个:

// header 1
struct base {};
void print(const base&);

// header 2
#include "header 1"
struct derived:base{};

// header 3
struct derived;
void print(const derived&);

重要的是要注意 print 函数是在不同的 TU 中定义的。现在比较这两个翻译单元:

// source 1
#include "header 2"

void foo() {
    derived d;
    print(d);
}

// source 2
#include "header 2"
#include "header 3"

void bar() {
    derived d;
    print(d);
}

print 的调用看起来是一样的,但是第一个源文件调用 print(const base&) 而第二个调用 print(const derived&)。这种行为是否合法且符合标准?还是我在某个时候陷入了 UB?

如果 print 是一个模板函数,那么我们用一个非模板方法重载 print 会怎么样(忽略模板方法可能被选择为非模板作为它可能匹配得更好,假设我们正确地重载它),合法性会改变吗?

提出这个问题的部分原因是想知道什么是合法和健全的定制来源,什么不是。标准库倾向于类模板的部分/显式特化。

最佳答案

这是合法的,但很脆弱。

如果您的 foo作为内联函数在 header 中,这将是有问题的,因为您可能会破坏 ODR(单一定义规则)。

foo然后会调用void print(const base&);void print(const derived&);取决于之前的包含。

foo可以重写为:

void foo() {
    derived d;
    print(static_cast<Base&>(d));
}

明确选择哪个重载。

What if print was a template function instead, so that we overloaded print

template <typename T> void print(const T&);

有了重载,就没有问题了。

通过特化,它将成为 foobar会用 print<derived> , 但使用不同的定义。

关于c++ - 有条件地添加到重载集是否合法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48942170/

相关文章:

c++ - 引用 this 指针 : GCC vs clang

c++ - QWidget 的背景应用到它所有的 QWidget child

c++ - 'const' 变量是否默认在 C++ 中预先计算?

c++ - 接收音频 block 的异步 TCP 服务器出现访问冲突错误

c++ - C++ 标准对于 move 事件对象存储有何规定?

c++ - 同时具有 'extern' 和 'inline' 说明符的变量

c++ - 模板参数包什么时候被推导为空?

C++ 默认构造函数与具有非平凡默认构造函数的变体成员 union

C++:使用具有特定(双...)指针参数的函数重载具有void *函数的函数

c++ - 回调:将函数指针作为参数并传递一个附加参数