【问题标题】:Why MSVC does not prefer non-template overloaded function over template one?为什么 MSVC 不喜欢模板一的非模板重载函数?
【发布时间】: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++


【解决方案1】:

是的,这看起来确实是一种回归。您可以在https://aka.ms/vs-rap 的 VC++ 开发人员社区中输入问题吗?

【讨论】:

  • 通过 VS2017 帮助 > 发送反馈 > 昨天报告问题,它已被分类,现在处于“考虑中”状态。
  • 可能是两阶段查找中的错误...enable_bitmask_operators 是一个依赖名称,因为它的参数类型是依赖的,并且将其视为非依赖将产生完全观察到的行为。
  • 谢谢!如果您让我知道您提交的标题,我可能会加快分类速度。
猜你喜欢
  • 2013-01-17
  • 1970-01-01
  • 2012-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
相关资源
最近更新 更多