【发布时间】:2017-08-28 15:10:55
【问题描述】:
在同一个翻译单元中,ODR 问题很容易诊断。那么为什么编译器不会针对同一翻译单元中的 ODR 违规发出警告呢?
例如,在以下代码https://wandbox.org/permlink/I0iyGdyw9ynRgny6(在下面重现)中,检测是否已定义std::tuple_size 时存在 ODR 冲突。此外,当您取消注释 three 和 four 的定义时,未定义的行为很明显。程序的输出发生变化。
只是想了解为什么 ODR 违规行为如此难以捕捉/诊断/可怕。
#include <cstdint>
#include <cstddef>
#include <tuple>
#include <iostream>
class Something {
public:
int a;
};
namespace {
template <typename IncompleteType, typename = std::enable_if_t<true>>
struct DetermineComplete {
static constexpr const bool value = false;
};
template <typename IncompleteType>
struct DetermineComplete<
IncompleteType,
std::enable_if_t<sizeof(IncompleteType) == sizeof(IncompleteType)>> {
static constexpr const bool value = true;
};
template <std::size_t X, typename T>
class IsTupleSizeDefined {
public:
static constexpr std::size_t value =
DetermineComplete<std::tuple_size<T>>::value;
};
} // namespace <anonymous>
namespace std {
template <>
class tuple_size<Something>;
} // namespace std
constexpr auto one = IsTupleSizeDefined<1, Something>{};
// constexpr auto three = IsTupleSizeDefined<1, Something>::value;
namespace std {
template <>
class tuple_size<Something> : std::integral_constant<int, 1> {};
} // namespace std
constexpr auto two = IsTupleSizeDefined<1, Something>{};
// constexpr auto four = IsTupleSizeDefined<1, Something>::value;
int main() {
std::cout << decltype(one)::value << std::endl;
std::cout << decltype(two)::value << std::endl;
}
【问题讨论】:
-
它不必根据标准诊断这些错误(即使它可以检测到这些错误也可以)。
-
@Jarod42 对,但为什么呢?
标签: c++ templates c++17 one-definition-rule