【发布时间】:2020-02-22 04:05:01
【问题描述】:
在我尝试过的每个 C++11 及更高版本的编译器中,以下代码都可以满足我的所有需求。因此,在实践中,就我的目的而言,它是有效的(并且由于历史原因,在可预见的将来,它至少可以在 Linux 上工作)。然而,从语言律师的角度来看,这段代码是无效的,因为它包含一个形式上是 UD 的构造(指向不存在对象的指针的解引用),即使这种解引用实际上从未执行过。
#include <type_traits>
#include <iostream>
namespace n1 {
struct int_based { int base = 0; };
inline int get_base(int_based ib) { return ib.base; }
}
namespace n2 {
struct double_based;
double get_base(const double_based&);
}
template <typename T>
using base_type = decltype((get_base(*(T*)nullptr)));
int main() {
auto isInt = std::is_same<base_type<n1::int_based>, int>::value;
auto isDouble = std::is_same<base_type<n2::double_based>, double>::value;
auto unlike = std::is_same<base_type<n1::int_based>, double>::value;
std::cout << isInt << isDouble << unlike << std::endl;
return 0;
}
代码执行 Koenig 查找类型映射并使用我不想更改的函数签名推断映射类型。在本例中,double_based 类型不完整;在我的实际用例中,类型应该是完整的,但不保证是DefaultConstructible。实际代码是类型安全序列化逻辑的一部分。
问题是:是否有一种符合标准的方式来“物化”模板参数类型 T 的对象以用于此代码中的 decltype,或者是否不可能有这种符合标准的类型映射没有源类型的预构造对象?
用指向对象的指针替换函数参数是丑陋的,并不能真正解决问题,因为在不引入另一个 UB 的情况下,在一般情况下不清楚这些函数需要用 nullptr 参数做什么。
【问题讨论】:
标签: c++ c++11 undefined-behavior type-inference