Проверьте, является ли тип экземпляром шаблона - PullRequest
0 голосов
/ 11 мая 2018

Я хочу проверить, является ли тип экземпляром конкретного шаблона во время компиляции.

Например:

  1. std::vector<int> является экземпляром std::vector
  2. std::array<int, 5> является экземпляром std::array

Я могу сделать тест, который работает для случая 1, но не работает для случая 2.

#include <iostream>
#include <type_traits>
#include <string>
#include <vector>
#include <array>
#include <queue>
template<template<typename...> class, typename...>
struct is_instantiation : public std::false_type {};

template<template<typename...> class U, typename... T>
struct is_instantiation<U, U<T...>> : public std::true_type {};

int main() {
    using A = std::vector<int>;
    std::cout << is_instantiation<std::vector, A>::value << "\n";
    std::cout << is_instantiation<std::queue, A>::value << "\n";
    // std::cout << is_instantiation<std::array, A>::value << "\n";
}

Как заставить это работать в обоих случаях?

Я пробовал авто, но не могу заставить его работать.

Преимущества auto в параметрах шаблона в C ++ 17

1 Ответ

0 голосов
/ 24 мая 2018

Специализированный std :: размер массива

Единственный способ, которым я вижу, - создавать специализированные классы Array с предопределенными размерами массивов. Примерно так:

#include <iostream>
#include <type_traits>
#include <string>
#include <vector>
#include <array>
#include <queue>
template<template<typename...> class, typename...>
struct is_instantiation : public std::false_type {};

template<template<typename...> class U, typename... T>
struct is_instantiation<U, U<T...>> : public std::true_type {};

template <class T> class My5Array {
    public:
    My5Array() { }
    private:
    std::array<T, 5> arr;
};

template <class T> class My10Array {
    public:
    My10Array() { }
    private:
    std::array<T, 10> arr;
};

int main() {
    using A = std::vector<int>;
    using B = My5Array<int>;
    std::cout << is_instantiation<std::vector, A>::value << "\n";
    std::cout << is_instantiation<std::queue, A>::value << "\n";
    std::cout << is_instantiation<My5Array, A>::value << "\n";
    std::cout << is_instantiation<My5Array, B>::value << "\n";
    std::cout << is_instantiation<My10Array, B>::value << "\n";
}

печать

1
0
0
1
0

Конечно, есть и недостатки:

  • возможно потеря памяти из-за фиксированного размера массива
  • несколько классов, необходимых для желаемых размеров массива
  • использование нестандартного типа MyXArray
  • очевидно, что экземпляр My5Array не может быть одновременно экземпляром My10Array (см. Var B в коде выше)

1-я возможная альтернатива: std :: dynarray

Я также нашел std :: dynarray, который мог бы работать вместо std :: array, но я думаю, что он еще не включен в последние стандарты C ++. Может быть, стоит присмотреть за этим.

2-ая возможная альтернатива: просто дайте ей упасть

Стандартный доступный контейнер может быть достаточным для большинства применений.

...