使用constexpr函数作为参数

时间:2017-09-10 18:25:52

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

我目前正在与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对我很宽容。

1 个答案:

答案 0 :(得分:0)

在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

这样做的好处是我们隐藏了来自呼叫者的第二个模板参数,无论如何他们都不关心。