【问题标题】:Is there a C++14 alternative to explicit(expr) introduced in C++20?是否有 C++14 替代 C++20 中引入的显式(expr)?
【发布时间】: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&lt;sz&gt; 表示长度为 sz 的位向量。转换为 bool 曾经对所有 sz 都是隐式的,但事实证明这很容易出错,因此我们将 operator bool() 更改为显式。

但是,1-bit 位向量(在我们的上下文中)几乎完全等同于布尔值,因此当 sz == 1 时,operator bool() 最好是隐式的。

这可以通过C++20 中的explicit(sz &gt; 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 &gt; 1 显式?

我在下面为好奇的读者提供了一些背景知识。

背景

这个问题是在 C++ 中的嵌入式领域特定语言的上下文中出现的。业务需求之一是operator== 返回bit&lt;1&gt;,而不是bool。这在 GNU 的 libstdc++ 上运行顺利,但我们在 macOS 上遇到了这个要求,因为 libstdc++ 使用带有谓词的std::equal 版本在std::array 上实现operator==,并使用结构实现该谓词其operator() 返回bool,正文为a == b(在我们的例子中返回bits&lt;1&gt;,导致转换错误)。

为了让好奇的读者具体了解一下,以下程序在 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


    【解决方案1】:

    是的。你canSFINAE 转换算子:

    #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
    }
    

    【讨论】:

      猜你喜欢
      • 2016-02-17
      • 2018-09-21
      • 2021-12-24
      • 2015-10-18
      • 2023-01-18
      • 2015-05-03
      相关资源
      最近更新 更多