Тип шаблона класса по умолчанию и условия - PullRequest
3 голосов
/ 12 января 2020

Я хочу использовать std :: enable_if для MyClass, чтобы принимать только (uint32_t | uint64_t) и в то же время, если пользователь не указал какой-либо тип; по умолчанию выбирается в соответствии с условиями ниже.

, но я не могу заставить его работать. (C ++ 17)

#include <vector>
#include <cstdint>

template <typename T=std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass
{
  private:
    std::vector<T> vs;
  public:
  // ...
};


int main(){
  MyClass a; // OK, the defaut type is used either uint32_t or uint64_t
  MyClass<std::uint32_t> b; // Ok, use the user provided type
  MyClass<long> c; // must not compile, T is not one of uint32_t, uint64_t
}

Ответы [ 2 ]

3 голосов
/ 12 января 2020

Вы можете добавить static_assert для выполнения проверки.

template <typename T=std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass
{
  static_assert(std::is_same_v<T, std::uint64_t> || std::is_same_v<T, std::uint32_t>, "T must be std::uint64_t or std::uint32_t");
  private:
    std::vector<T> vs;
  public:
  // ...
};

LIVE

0 голосов
/ 12 января 2020

Решение, предложенное songyanyao с static_assert, является хорошим, полностью действительным и короче, чем то, что я предлагаю ниже. Еще ...

Предлагая другую альтернативу, позволяя компилятору проверять вас без необходимости static_assert:

template <typename T>
class MyClassBase {
    std::vector<T> vs;
  public:
  // ...
};

template <typename T =
            std::conditional_t<sizeof(void*) == 8, std::uint64_t, std::uint32_t>>
class MyClass;

template <>
class MyClass<std::uint64_t>: public MyClassBase<std::uint64_t> {};

template <>
class MyClass<std::uint32_t>: public MyClassBase<std::uint32_t> {};

http://coliru.stacked-crooked.com/a/66033e773f001379

...