-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Open
Labels
bugSomething isn't workingSomething isn't working
Description
This should compile, but doesn't:
C:\Temp>type meow.cpp
template <typename T, typename U> void operator&(T&&, U&&) = delete;
template <typename T, typename U> void operator|(T&&, U&&) = delete;
template <typename T, typename U> void operator^(T&&, U&&) = delete;
template <typename T, typename U> void operator&=(T&&, U&&) = delete;
template <typename T, typename U> void operator|=(T&&, U&&) = delete;
template <typename T, typename U> void operator^=(T&&, U&&) = delete;
template <typename T> void operator~(T&&) = delete;
#include <iostream>
int main() {
std::cout << 1729 << "\n";
}
C:\Temp>cl /EHsc /nologo /W4 meow.cpp
meow.cpp
S:\msvc\binaries\amd64chk\inc\xlocale(1059): error C2280: 'void operator &<const std::_Codecvt_mode&,std::_Codecvt_mode>(T,U &&)': attempting to reference a deleted function
with
[
T=const std::_Codecvt_mode &,
U=std::_Codecvt_mode
]
meow.cpp(1): note: see declaration of 'operator &'
S:\msvc\binaries\amd64chk\inc\xlocale(1125): error C2280: 'void operator &<const std::_Codecvt_mode&,std::_Codecvt_mode>(T,U &&)': attempting to reference a deleted function
with
[
T=const std::_Codecvt_mode &,
U=std::_Codecvt_mode
]
meow.cpp(1): note: see declaration of 'operator &'
[...19 more errors...]
This happens when the STL uses an enum as a bitmask:
Line 894 in 58bb49d
| enum _Codecvt_mode { _Consume_header = 4, _Generate_header = 2 }; |
Line 1059 in 58bb49d
| if ((_Mode & _Consume_header) != 0 && _Ch == 0xfeffu) { // drop header and retry |
without defining dedicated bitmask operators:
Lines 2048 to 2089 in 58bb49d
| #define _BITMASK_OPS(_BITMASK) \ | |
| _NODISCARD constexpr _BITMASK operator&(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left & _Right */ \ | |
| using _IntTy = _STD underlying_type_t<_BITMASK>; \ | |
| return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) & static_cast<_IntTy>(_Right)); \ | |
| } \ | |
| \ | |
| _NODISCARD constexpr _BITMASK operator|(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left | _Right */ \ | |
| using _IntTy = _STD underlying_type_t<_BITMASK>; \ | |
| return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) | static_cast<_IntTy>(_Right)); \ | |
| } \ | |
| \ | |
| _NODISCARD constexpr _BITMASK operator^(_BITMASK _Left, _BITMASK _Right) noexcept { /* return _Left ^ _Right */ \ | |
| using _IntTy = _STD underlying_type_t<_BITMASK>; \ | |
| return static_cast<_BITMASK>(static_cast<_IntTy>(_Left) ^ static_cast<_IntTy>(_Right)); \ | |
| } \ | |
| \ | |
| constexpr _BITMASK& operator&=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left &= _Right */ \ | |
| return _Left = _Left & _Right; \ | |
| } \ | |
| \ | |
| constexpr _BITMASK& operator|=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left |= _Right */ \ | |
| return _Left = _Left | _Right; \ | |
| } \ | |
| \ | |
| constexpr _BITMASK& operator^=(_BITMASK& _Left, _BITMASK _Right) noexcept { /* return _Left ^= _Right */ \ | |
| return _Left = _Left ^ _Right; \ | |
| } \ | |
| \ | |
| _NODISCARD constexpr _BITMASK operator~(_BITMASK _Left) noexcept { /* return ~_Left */ \ | |
| using _IntTy = _STD underlying_type_t<_BITMASK>; \ | |
| return static_cast<_BITMASK>(~static_cast<_IntTy>(_Left)); \ | |
| } \ | |
| \ | |
| _NODISCARD constexpr bool _Bitmask_includes( \ | |
| _BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) != _BITMASK{} */ \ | |
| return (_Left & _Elements) != _BITMASK{}; \ | |
| } \ | |
| \ | |
| _NODISCARD constexpr bool _Bitmask_includes_all( \ | |
| _BITMASK _Left, _BITMASK _Elements) noexcept { /* return (_Left & _Elements) == _Elements */ \ | |
| return (_Left & _Elements) == _Elements; \ | |
| } |
The test case has pathological overloads, but users can and have encountered this with reasonable code (typically, when they define templated operators to handle their own enums).
Curiously, this doesn't happen in /std:c++17 or /std:c++latest mode. I haven't analyzed why, but this is definitely a problem in /std:c++14 mode.
We should audit the entire STL for this problem.
Also tracked by Microsoft-internal VSO-115352 / AB#115352.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working