为什么带有unsigned long long参数的std :: bitset构造函数没有标记为显式? [英] Why is the std::bitset constructor with an unsigned long long argument not marked as explicit?

查看:240
本文介绍了为什么带有unsigned long long参数的std :: bitset构造函数没有标记为显式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准库类模板 std :: bitset< N> 有一个构造函数(C ++ 11及以上, unsigned long C ++之前的参数11)

The Standard Library class template std::bitset<N> has a constructor (C++11 and onwards, unsigned long argument before C++11)

constexpr bitset(unsigned long long) noexcept 

与许多最佳实践指南相反,此单参数构造函数未标记为 explicit 。这背后的理由是什么?

Contrary to many best-practice guidelines, this single-argument constructor is not marked as explicit. What is the rationale behind this?

推荐答案

显式构造



显式构造函数的主要反对是无符号整数的复制初始化不再起作用

Explicit construction

The main objection against an explicit constructor is that copy-initialization from unsigned integers no longer works

constexpr auto N = 64;
std::bitset<N> b(0xDEADC0DE);  // OK, direct initialization
std::bitset<N> b = 0xDEADC0DE; // ERROR, copy initialization cannot use explicit constructors

由于 std :: bitset< ; N> 意味着 unsigned int 的泛化,构造函数可能被隐式地促进适应现有的C风格的基于比特 - on raw unsigned int 。使构造函数 explicit 会破坏很多现有代码(现在添加它将同样打破现有代码)。

Since std::bitset<N> is meant as a generalization of unsigned int, the constructor was probably made implicit to facilitate adapting existing C-style bit-twiddling code based on raw unsigned int. Making the constructor explicit would have broken much existing code (and adding it now will equally break much existing code).

UPDATE :执行一些标准考古学,我发现的sc22 / wg21 / docs / papers / 1995 / N0624.ascrel =nofollow> N0624 > explicit 到标准库前的所有单参数构造函数。这是在1995年3月的一次会议上(奥斯汀)进行表决的。如 N0661 中所述 bitset unsigned long 构造函数未作显式(一致投票,但没有动机)。

UPDATE: doing some Standard archeology, I found N0624 from January 1995 that proposed to add the then brand-new keyword explicit to all single-argument constructors in the pre-Standard Library draft. This was put to a vote at a meeting in March 1995 (Austin). As documented in N0661, the unsigned long constructor for bitset was not made explicit (unanimous vote, but without motivation).

即使 bitset 很容易从 unsigned long 初始化,但是存在其他不完全的混合模式网络操作(& | ^ ):

However, even though bitset is easily initialized from unsigned long, there is otherwise incomplete mixed-mode setwise operations (&, | or ^):

 constexpr auto N = 512;
 std::bitset<N> b = 0xDEADC0DE; // OK
 std::bitset<N> c = b & 0xFFFF; // ERROR, cannot deduce template arguments for rhs

这可以通过提出重载操作符来支持混合-mode bit-twiddling:

This could be remedied by proposing overloaded operators to support mixed-mode bit-twiddling:

 // @ from { &, |, ^ }

 template<std::size_t N> 
 bitset<N> operator@(unsigned long long lhs, const bitset<N>& rhs)

 template<std::size_t N> 
 bitset<N> operator@(const bitset<N>& lhs, unsigned long long rhs)



作为成员的重载运算符(< N&函数



关于混合模式功能的 std :: bitset 的精神分裂性质也存在于 operator == operator!= 。这些是对其rhs参数进行隐式转换的成员函数,但不是它们的lhs参数( this 指针,它受模板参数扣除)。这导致以下结果:

Overloaded operators as member functions

The schizophrenic nature of std::bitset with respect to mixed-mode functionality is also present in the operator== and operator!=. These are member functions that have implicit conversion on their rhs arguments, but not on their lhs argument (the this pointer, which is subject to template argument deduction). This leads to the following:

#include <bitset>
#include <iostream>

int main()
{
    constexpr auto N = 64;
    constexpr std::bitset<N> b = 0xDEADC0DE; // OK, copy initialization

    std::cout << (b == 0xDEADC0DE);     // OK, implicit conversion on rhs
    std::cout << (0xDEADC0DE == b);     // ERROR, no implicit conversion on lhs
}

1992年提案 N0128 。主要锁定未来功能的提议的时间 std :: bitset 早于具有非类型模板参数的功能模板。当时唯一可行的解​​决方法是使所有重载的运算符成员函数,而不是非成员函数。以后,当更高级的模板技术开始使用时,这种情况从未改变过(另见 此问答 为什么这可能破坏代码)。

The origins of this behavior stem from the 1992 proposal N0128. The timing of that proposal, which largely locked in the functionality of the future std::bitset, was prior to function templates having non-type template parameters. The only feasible workaround at the time was to make all overloaded operators member functions instead of non-member functions. This was never changed later on when more advanced template technology became available (see also this Q&A for why this might break code).

这篇关于为什么带有unsigned long long参数的std :: bitset构造函数没有标记为显式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆