是否有 C++20 中引入的 explicit(expr) 的 C++14 替代方案?
Is there a C++14 alternative to explicit(expr) introduced in C++20?
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++ class bits<sz>
表示长度为 sz
的位向量。向 bool
的转换过去对所有 sz
都是隐式的,但事实证明这很容易出错,因此我们将 operator bool()
更改为显式的。
然而,1-bit
位向量(在我们的上下文中)几乎完全等同于布尔值,因此当 sz == 1
.[=46 时 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==
returns 一个 bit<1>
,而不是 bool
。这与 GNU 的 libstdc++ 一起工作顺利,但我们 运行 在 macOS 上遇到了这个要求的麻烦,因为 libstdc++ 使用 std::equal
的版本在 std::array
上实现了 operator==
一个谓词,并使用 operator()
returns bool
和主体 a == b
的结构来实现该谓词(在我们的例子中 returns a bits<1>
,导致转换错误)。
为了让好奇的读者具体了解,以下程序在 GNU 上编译良好,但在 macOS 上编译不好,因为 operator==
on std::array
的实现方式:
#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))
和 __pred
大致等同于 bool __pred(S a, S b) { return a == b; }
,它不进行类型检查。
是的。你can SFINAE 转换运算符:
#include <type_traits>
template<int sz>
struct bits {
int v;
explicit operator bool() const { return bool(v); }
template <int S = sz>
operator std::enable_if_t<S == 1, bool> () const { return bool(v);}
};
检查一下on godbolt
int main()
{
bool c1 = bits<1>{1}; // Ok
bool c2 = bits<3>{1}; // error cannot convert
bool c3 = static_cast<bool>(bits<3>{1}); // OK
}
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++ class bits<sz>
表示长度为 sz
的位向量。向 bool
的转换过去对所有 sz
都是隐式的,但事实证明这很容易出错,因此我们将 operator bool()
更改为显式的。
然而,1-bit
位向量(在我们的上下文中)几乎完全等同于布尔值,因此当 sz == 1
.[=46 时 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==
returns 一个 bit<1>
,而不是 bool
。这与 GNU 的 libstdc++ 一起工作顺利,但我们 运行 在 macOS 上遇到了这个要求的麻烦,因为 libstdc++ 使用 std::equal
的版本在 std::array
上实现了 operator==
一个谓词,并使用 operator()
returns bool
和主体 a == b
的结构来实现该谓词(在我们的例子中 returns a bits<1>
,导致转换错误)。
为了让好奇的读者具体了解,以下程序在 GNU 上编译良好,但在 macOS 上编译不好,因为 operator==
on std::array
的实现方式:
#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))
和 __pred
大致等同于 bool __pred(S a, S b) { return a == b; }
,它不进行类型检查。
是的。你can SFINAE 转换运算符:
#include <type_traits>
template<int sz>
struct bits {
int v;
explicit operator bool() const { return bool(v); }
template <int S = sz>
operator std::enable_if_t<S == 1, bool> () const { return bool(v);}
};
检查一下on godbolt
int main()
{
bool c1 = bits<1>{1}; // Ok
bool c2 = bits<3>{1}; // error cannot convert
bool c3 = static_cast<bool>(bits<3>{1}); // OK
}