C ++:在模板别名中使用static_assert

时间:2019-07-10 08:42:34

标签: c++ c++14

是否可以将static_assert与模板别名结合使用?我了解如何将SFINAE与模板别名一起使用,以及如何将static_assertstruct一起使用,但是我希望将static_assert与别名一起提供更清晰的错误消息。

我想到了以下用例:

#include <array>

constexpr bool is_valid(int n){
    return n <= 10;
}

template <int n>
struct Foo {
    static_assert(is_valid(n), "This class cannot handle more than 10 dimensions");
};

template <int n>
using Bar = std::array<float,n>;  

template <int n, std::enable_if_t<is_valid(n)> * unused = nullptr>
using BarSFINAE = std::array<float,n>;  

int main() {

    Foo<5>();
    // Foo<20>(); // Triggers the compiler-time static_assert

    Bar<5>();
    Bar<20>(); // TODO: Should trigger a compiler-time static_assert

    BarSFINAE<5>();
    // BarSFINAE<20>(); // Not allowed due to SFINAE, but throws an ugly compile time message
}

问题本质上是别名没有主体。因此,我什至不知道将static_assert放在哪里。

2 个答案:

答案 0 :(得分:5)

正确识别问题后,解决方案是添加一些别名可以依赖的正文。例如,一个函数。

namespace detail {
    template<std::size_t N>
    constexpr auto checked_size() {
        static_assert(is_valid(N), "");
        return N;
    }
}

template <int n>
using Bar = std::array<float, detail::checked_size<n>()>;  

答案 1 :(得分:2)

是的,您可以通过使用如下辅助结构来实现:

template<typename T>
struct A {};

template<int n, typename T>
struct B_impl {
  static_assert(n <= 10,
      "this is a demonstration");
  using type = A<T>;
};

template<int n, typename T>
using B = typename B_impl<n, T>::type;

using B_good = B<3, int>;

using B_bad = B<11, int>;

int main() {
  B_good good; // works
  B_bad bad; // static assertion failure
}