2015-03-08 2 views
6

Я уже знаю, что вы можете включить (или нет) метод класса за помощью std::enable_ifвключить члена класса, в зависимости от шаблона

для Exemple:

template<size_t D, size_t E> 
class Field 
{ 
    ... 

    size_t offset(const std::array<float,D>& p) const 
    { 
    ... 
    } 

    template<typename TT = size_t> 
    typename std::enable_if<D!=E, TT>::type 
    offset(const std::array<float,E>& p) const 
    { 
    return offset(_projection(p)); 
    } 

    ... 
}; 

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

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

Я пытался сделать

template<size_t D, size_t E> 
class Field 
{ 
    ... 

    template<typename TT = projectionFunc> 
    typename std::enable_if<D!=E, TT>::type _projection; 
} 

Но компилятор говорит мне:

erreur: data member ‘_projection’ cannot be a member template 

Is есть ли способ достичь того, чего я хочу?

+3

Возможно, вы захотите изменить имя из 'offsetof', чтобы кто-то включил перед заголовком и включил макрос. – chris

+0

Это запланировано, я просто ищу еще одно приятное имя. – Amxx

+0

. Именно этот SFINAE тоже немного ... icky. В случае 'D == E' вы получите« typename std :: enable_if :: type'. Специализацией стандартной формы типа библиотеки является UB, поэтому можно утверждать, что гипотетическая реализация может вызывать правило «недействительной специализации может быть сгенерировано» и называть это плохо сформированным. –

ответ

5

Держите данные в отдельном классе, которые затем можете специализировать по мере необходимости.

template<size_t D, size_t E> 
class Field { 
    template<size_t, size_t> struct Field_Members { 
     int _projection; 
    }; 
    template<size_t V> struct Field_Members<V, V> { }; 
    Field_Members<D, E> m; 
}; 

, а затем использовать m._projection и т.д.

Field_Members не должен быть шаблоном вложенным классом; вы можете переместить его снаружи, если это необходимо. Также возможно унаследовать от него Field, но тогда это будет зависимая база, и вам нужно будет написать this->_projection, так что это не сэкономит много ввода.

4

AFAIK, это невозможно с помощью простой SFINAE внутри шаблона класса. Конечно, вы можете иметь тип члена, зависящий от условия времени компиляции, то есть через std::conditional, но не полностью исключая его.

Что вы можете сделать, конечно, использовать другой шаблон класса, такие как

template<bool Condition, typename T> struct Has { T value; }; 
template<typename T> struct Has<false,T> {}; 

и объявить элемент (или основание) этого типа, и получить доступ к объекту с помощью Has<>::value:

typename<Condition> 
class foo 
{ 
    Has<Condition, double> x; // use x.value (only if Condition==true) 
}; 
Смежные вопросы