C ++: использование static_assert в псевдониме шаблона - PullRequest
2 голосов
/ 10 июля 2019

Можно ли использовать static_assert в сочетании с псевдонимом шаблона? Я понимаю, как использовать SFINAE с псевдонимом шаблона и как использовать static_assert с struct, но я хочу, чтобы 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 ]

5 голосов
/ 10 июля 2019

Поскольку вы правильно определили проблему, решение состоит в том, чтобы добавить что-то с телом, от которого может зависеть псевдоним.Например, функция.

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>()>;  
2 голосов
/ 10 июля 2019

Да, вы можете сделать это с помощью вспомогательной структуры, например:

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
}
...