2015-11-19 3 views
1

Я хотел создать шаблон для числовых значений, и для данного типа я хотел бы предоставить значения по умолчанию для значений min и max.Создание шаблона с аргументами по умолчанию на основе типа

Я нашел решение, которое работает до сих пор ...

template<typename T> struct MinDefaultValue; 
template<typename T> struct MaxDefaultValue; 
template<typename T, usize_t MinDefault = MinDefaultValue<T>::value, usize_t MaxDefault = MaxDefaultValue<T>::value> 
class NumericColumn 
{ 
public: 

public: 
    NumericColumn(T *pAddress, T nDefault, usize_t nMinValue = MinDefault, usize_t nMaxValue = MaxDefault) 
    { 
     mAddress = pAddress; 
     mDefault = nDefault; 
     mMinValue = nMinValue; 
    } 

    bool toValue(void) 
    { 
     return true; 
    } 

private: 
    T *mAddress; 
    usize_t mMinValue; 
    usize_t mMaxValue; 
    T mDefault; 
}; 
template <> struct MinDefaultValue<byte_t> { static const usize_t value = (usize_t)CHAR_MIN; }; 
template <> struct MaxDefaultValue<byte_t> { static const usize_t value = (usize_t)CHAR_MAX; }; 

Причина, почему мне не нравится это, потому что теперь Min- и MaxDefaultValue находится вне класса имен, в то время как она принадлежит внутри него.

Проблема заключается в том, что я не знаю, как определить специализации для различных типов, потому что сам родительский класс также является шаблоном.

Я изменил класс это:

template<typename T> 
class NumericColumn 
{ 
public: 
    template<typename T> struct MinDefaultValue; 
    template<typename T> struct MaxDefaultValue; 

public: 
    NumericColumn(T *pAddress, T nDefault, usize_t nMinValue = MinDefaultValue<T>::value, usize_t nMaxValue = MaxDefaultValue<T>::value) 
    { 
     mAddress = pAddress; 
     mDefault = nDefault; 
     mMinValue = nMinValue; 
    } 

    bool toValue(void) 
    { 
     return true; 
    } 

private: 
    T *mAddress; 
    usize_t mMinValue; 
    usize_t mMaxValue; 
    T mDefault; 
}; 

Но когда я пытаюсь обеспечить spezialisations я получаю ошибку компиляции:

template <> struct NumericColumn<byte_t>::MinDefaultValue<byte_t> { static const usize_t value = (usize_t)CHAR_MIN; }; 
template <> struct NumericColumn<byte_t>::MaxDefaultValue<byte_t> { static const usize_t value = (usize_t)CHAR_MAX; }; 

'class' : invalid or missing type parameter list 
+0

Вы специализируетесь на 'MinDefaultValue ' для 'NumericColumn '. Вам не нужен шаблон <> template <> '? – LogicStuff

+0

Что это значит? Разве я не должен предоставлять тип специализации? – Devolus

+0

Теперь я не знаю, что вы имеете в виду.Я только догадался, что придумал [это] (http://coliru.stacked-crooked.com/a/5dbc7e3b56fcd44c), но у вас уже есть лучший ответ. – LogicStuff

ответ

2

Я думаю, ваш второй подход не совсем то, что вам значит, это так. Наличие MinDefaultValue и MaxDefaultValue в качестве внутренних классов шаблонов означает, что каждый экземпляр шаблона NumericColumn<T> будет иметь отдельный шаблонный класс. Таким образом, NumericColumn<int>::MaxDefaultValue<int> - это отдельный тип от NumericColumn<float>::MaxDefaultValue<float>.

Может быть, что вы хотите простой static const элемент, который вы специализируетесь для каждого типа:

template<typename T> 
class NumericColumn 
{ 
public: 
    static const std::size_t MinDefaultValue; 
    static const std::size_t MaxDefaultValue; 

public: 
    NumericColumn(T *pAddress, T nDefault, 
        std::size_t nMinValue = MinDefaultValue, 
        std::size_t nMaxValue = MaxDefaultValue) 
     : mAddress{pAddress}, mDefault{pDefault}, 
      mMinValue{nMinValue}, mMaxValue{mMaxValue} 
    { } 
}; 

template<> 
const std::size_t NumericColumn<int>::MinDefaultValue = 1; 
template<> 
const std::size_t NumericColumn<int>::MaxDefaultValue = 10; 

Заметим, что если вы не определяете специализаций члена для некоторой NumericType специализации, вы получите ошибку линии связи, когда который создается. Возможно, это то, что вы хотите, может быть, нет.


Вот возможный способ получить лучшее сообщение об ошибке за счет некоторой краткости:

template <typename T> 
struct dependent_false : std::false_type {}; 

template<typename T> 
class NumericColumn 
{ 
public: 
    struct MinDefault{ 
     static_assert(dependent_false<T>::value, 
         "T does not have a minimum default defined"); 
    }; 
    struct MaxDefault{ 
     static_assert(dependent_false<T>::value, 
         "T does not have a maximum default defined"); 
    }; 

public: 
    NumericColumn(T *pAddress, T nDefault, 
        std::size_t nMinValue = MinDefault::value, 
        std::size_t nMaxValue = MaxDefault::value) 
     : mAddress{pAddress}, mDefault{pDefault}, 
      mMinValue{nMinValue}, mMaxValue{mMaxValue} 
    { } 
}; 

template<> 
struct NumericColumn<int>::MinDefault { 
    static constexpr std::size_t value = 1; 
}; 

template<> 
struct NumericColumn<int>::MaxDefault { 
    static constexpr std::size_t value = 10; 
}; 
+0

Да, я хочу получить сообщение об ошибке, так что пользователь знает, что тип не полностью реализован или поддерживается. – Devolus

+0

@Devolus круто, тогда это должно сработать для вас. Может быть, есть способ получить лучшую ошибку, чем есть в настоящее время, я подумаю об этом. – TartanLlama

+0

Да. Правильное сообщение об ошибке будет лучше, но это работает так, как я предполагал. :) – Devolus

0

Я не думаю, что вы можете специализировать шаблон внутри класса шаблона. Я ожидаю, что кто-то, кто знает стандарт C++, лучше, чем я могу это сделать.

Вы могли бы, возможно, использовать подкладку доступа:

template <typename TColumn, typename T> inline T MinDefaultValue(); 

// specialization: 
template <> inline byte_t MinDefaultValue<NumericColumn<byte_t>,byte_t>() { 
    return 5; 
} 

Вы, вероятно, может уменьшить это вниз, поставив ЬурейеЕ в вашем колонного типа:

typedef T value_type; 

А потом что-то вдоль линий:

template <typename TColumn> inline typename T::value_type MinDefaultValue(); 

// specialization: 
template <> inline byte_t MinDefaultValue<NumericColumn<byte_t> >() { 
    return 5; 
} 

Затем это позволяет специализацию значения min для типа класса столбца.

Это не удастся, если нет специализации.

+0

Вы можете специализировать вложенный шаблонный класс, вам просто нужно использовать 'template <> template <>'. – TartanLlama

+0

@TartanLlama cool - спасибо за это – Pete

Смежные вопросы