【发布时间】:2022-03-04 15:43:03
【问题描述】:
TL;DR:我正在寻找与以下 C++20 MWE 等效的 C++14:
template<int sz>
struct bits {
int v; // note explicit(expr) below
explicit(sz > 1) operator bool() const { return bool(v); }
};
int main() {
bool c = bits<1>{1}; // Should work
bool d = bits<3>{1}; // Should fail
}
上下文:
我们有一个 C++ 类 bits<sz> 表示长度为 sz 的位向量。转换为 bool 曾经对所有 sz 都是隐式的,但事实证明这很容易出错,因此我们将 operator bool() 更改为显式。
但是,1-bit 位向量(在我们的上下文中)几乎完全等同于布尔值,因此当 sz == 1 时,operator bool() 最好是隐式的。
这可以通过C++20 中的explicit(sz > 1) 来实现,但我们的目标是C++14。
我试图重载sz == 1 的运算符,但似乎explicit 限定符也适用于它:以下不起作用。
template<int sz>
struct bits {
int v;
explicit operator bool() const { return bool(v); }
};
template<> bits<1>::operator bool() const {
return bool(v);
}
int main() {
bool c = bits<1>{1}; // Fails: "No viable conversion"
}
因此问题是:如何在 C++14 中指定 operator bool() 应该只对 sz > 1 显式?
我在下面为好奇的读者提供了一些背景知识。
背景:
这个问题是在 C++ 中的嵌入式领域特定语言的上下文中出现的。业务需求之一是operator== 返回bit<1>,而不是bool。这在 GNU 的 libstdc++ 上运行顺利,但我们在 macOS 上遇到了这个要求,因为 libstdc++ 使用带有谓词的std::equal 版本在std::array 上实现operator==,并使用结构实现该谓词其operator() 返回bool,正文为a == b(在我们的例子中返回bits<1>,导致转换错误)。
为了让好奇的读者具体了解一下,以下程序在 GNU 上编译得很好,但在 macOS 上编译得不好,因为 std::array 上的 operator== 的实现方式:
#include <array>
struct S { explicit operator bool() const { return true; } };
struct T {};
S operator==(T, T) { return S(); }
int main() {
std::array<T, 1> arr = { T() };
return arr == arr;
}
这是因为在数组 GNU libstdc++ 的== 实现的深处有一个测试if (!(*it1 == *it2)),它可以毫无问题地调用S 上的explicit operator bool(),而在macOS 上,库使用if (!__pred(*it1, *it2)) 和@ 987654355@ 大致相当于bool __pred(S a, S b) { return a == b; },它不进行类型检查。
【问题讨论】:
标签: c++ c++14 c++20 implicit-conversion template-meta-programming