Использование enable_if со структурной специализацией
Я пытаюсь определить шаблон, который будет указывать тип хранилища, заданный другим типом T. Я хотел бы использовать enable_if для перехвата всех арифметических типов. Ниже моя попытка этого, которая жалуется, что шаблон повторно объявлен с 2 параметрами. Я попытался добавить второй фиктивный параметр в основной шаблон, но получил другую ошибку. Как это может быть сделано?
#include <string>
#include <type_traits>
template <typename T> struct storage_type; // want compile error if no match
// template <typename T, typename T2=void> struct storage_type; // no joy
template <> struct storage_type<const char *> { typedef std::string type; };
template <> struct storage_type<std::string> { typedef std::string type; };
template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
struct storage_type { typedef double type; };
// Use the storage_type template to allocate storage
template<typename T>
class MyStorage {
public:
typename storage_type<T>::type storage;
};
MyStorage<std::string> s; // uses std::string
MyStorage<const char *> s2; // uses std::string
MyStorage<float> f; // uses 'double'
1 ответ
Вы можете сделать это, добавив второй параметр в основной шаблон, а затем специализируясь на его сопоставлении; Вы были на правильном пути, но не сделали это правильно.
#include <string>
#include <type_traits>
// template <typename T> struct storage_type; // Don't use this one.
template <typename T, typename T2=void> struct storage_type; // Use this one instead.
template <> struct storage_type<const char *> { typedef std::string type; };
template <> struct storage_type<std::string> { typedef std::string type; };
// This is a partial specialisation, not a separate template.
template <typename T>
struct storage_type<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
typedef double type;
};
// Use the storage_type template to allocate storage
template<typename T>
class MyStorage {
public:
typename storage_type<T>::type storage;
};
MyStorage<std::string> s; // uses std::string
MyStorage<const char *> s2; // uses std::string
MyStorage<float> f; // uses 'double'
// -----
struct S {};
//MyStorage<S> breaker; // Error if uncommented.