【问题标题】:enable_if not working in Visual Studio when using a constexpr function as argument使用 constexpr 函数作为参数时 enable_if 在 Visual Studio 中不起作用
【发布时间】:2017-09-10 18:25:51
【问题描述】:

我目前正在与 Visual Studio 2017 搏斗(如果有帮助,请使用 /std:c++latest 进行编译)。

有问题的代码只是根据一些模板化的constexpr 函数的结果选择一个结构特化。 GCC 和 clang 编译都没有问题。

这是我的 MCVE:

#include <type_traits>

struct A {
  enum {
    test_trait = true
   };
};

template<typename T>
constexpr int choose() {
  return T::test_trait;
}

template<typename T, typename Enable=void>
struct Chosen;

template<typename T>
struct Chosen<T, std::enable_if_t<choose<T>() == 1>> {};

void foo() {
  // This works
  constexpr int chosen = choose<A>();
  static_assert(chosen == 1, "");

  // This resolves to the undefined struct.
  using Chosen_t = Chosen<A>;
  Chosen_t x;
  (void)x;
}

choose() 在我的代码库中实际上要复杂一些,但static_assert 仍然可以编译,并且检查正常。

我有点假设如果 static_assert 编译,enable_if 没有理由不能发挥它的魔力。我错了吗?我猜“也许”T 在技术上不是enable_if 的依赖类型...但如果是这样的话,我希望 GCC 和 clang 会拍我的手腕。

我可以通过将choose() 的结果包装在std::integral_constant 中来解决这个问题,如下所示:

template<typename T> 
struct Chooser : public std::integral_constant<int, choose<T>()> {};

template<typename T>
struct Chosen<T, std::enable_if_t<Chooser<T>::value>> {};

但我真的不想跳过那个圈子。

模板解析应该能够以我期望的方式解决这个问题吗?我担心代码实际上是错误的,而 GCC 和 clang 只是对我宽容。

【问题讨论】:

  • 这适用于 VS 2015 吗?这可能是与this相关的错误
  • @Justin 刚刚检查:没有,Visual Studio 2015 似乎有同样的错误。
  • VC++ 在模板方面被严重破坏了。代码完全没问题。采用您的解决方法并收工?
  • @Columbo,如果我的代码不能以可移植的方式使用,我不会称它为“好” :(。但是,不幸的是,我想这将不得不这样做。跨度>

标签: c++ visual-studio c++14 constexpr enable-if


【解决方案1】:

MSVC 19.00.23506 中的代码似乎仍然被破坏。但是,它似乎只适用于多一层间接性(也许是更好的解决方法):

template<typename T, bool>
struct ChosenImpl;

template<typename T>
struct ChosenImpl<T, true> {};

template<typename T>
using Chosen = ChosenImpl<T, choose<T>()>;

Demo

这样做的好处是我们向调用者隐藏了第二个模板参数,而他们无论如何都不关心。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 2019-01-30
    相关资源
    最近更新 更多