【发布时间】:2018-02-04 17:37:41
【问题描述】:
我无法弄清楚为什么以下代码(带有未定义的USE_TEMPLATE_SPECIALIZATION)在 Clang 中可以正常编译,但在 Visual Studio 15.5.5 中编译失败:
#include <iostream>
#include <type_traits>
// Defining USE_TEMPLATE_SPECIALIZATION fixes MSVC but breaks CLang...
//#define USE_TEMPLATE_SPECIALIZATION
//-----------------------------------------------------
#ifdef USE_TEMPLATE_SPECIALIZATION
template<typename Enum>
struct EnableBitMaskOperators {
static const bool enable = false;
};
template<typename E>
constexpr typename std::enable_if<EnableBitMaskOperators<E>::enable, bool>::type
isSet(E e, E mask)
{
using underlying_t = typename std::underlying_type<E>::type;
return (static_cast<underlying_t>(e) & static_cast<underlying_t>(mask)) != 0;
}
#define ENABLE_BITMASK_OPERATORS(x) \
template<> \
struct EnableBitMaskOperators<x> { \
static const bool enable = true; \
};
#else //-------------------------------------------------
template<typename E>
constexpr bool enable_bitmask_operators(E) { return false; }
template<typename E>
constexpr typename std::enable_if<enable_bitmask_operators(E{}), bool>::type
isSet(E e, E mask)
{
using underlying_t = typename std::underlying_type<E>::type;
return (static_cast<underlying_t>(e) & static_cast<underlying_t>(mask)) != 0;
}
#define ENABLE_BITMASK_OPERATORS(x) constexpr bool enable_bitmask_operators(x){ return true; }
#endif
//-----------------------------------------------------
namespace NOne {
namespace NTwo {
enum class ENUM_FLAGS {
NONE = 0,
ONE = 1,
TWO = 2,
};
ENABLE_BITMASK_OPERATORS(ENUM_FLAGS);
}}
using namespace NOne::NTwo;
int main(int, char**)
{
auto a = ENUM_FLAGS::NONE;
std::cout << (isSet(a, ENUM_FLAGS::TWO)? "Should not happen" : "Bitwise flags work!") << std::endl;
return 0;
}
很清楚为什么在第 5 行定义 USE_TEMPLATE_SPECIALIZATION 会破坏 Clang,但令人惊讶的是,它修复了 MSVC。
我真的很想弄清楚为什么第二种方法,非模板函数重载,不适用于 MSVC(我真的希望这不是 MSVC 错误,因为我相信它曾经可以工作),并感谢您的帮助!
感谢您的收看!
【问题讨论】:
-
是的,这似乎是 MSVC 回归:我刚刚将平台工具集从“Visual Studio 2017 (v141)”切换到“Visual Studio 2015 (v140)”,未定义的 USE_TEMPLATE_SPECIALIZATION 的代码编译得很好!
-
Godbolt 的编译器资源管理器中的代码的较短版本:godbolt.org/g/BM8H1z 甚至像 CLang 3.8 或 GCC 5.1 这样的旧编译器也编译此代码,只有 MSVC 19 失败...
标签: c++ templates visual-c++