2016-01-10 3 views
0

Я разрабатываю приложение для встроенного устройства, поэтому у меня нет type_traits и enable_if (плохое качество компилятора). Я создал их сам по себе:C++ enable_if в классе - разные способы уничтожения

template <typename T> 
struct is_pointer_t{ 
    enum{value = false}; 
}; 

template <typename T> 
struct is_pointer_t<T*>{ 
    enum{value = true}; 
}; 

и объявления для всего напоминает consts и volatiles.

Сейчас реализация enable_if:

template <bool boolean, typename T = void> 
struct enable_if{}; 

template <typename T> 
struct enable_if<true, T>{ 
    typedef T type; 
}; 

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

template <typename T> 
class pointerOrNot{ 
public: 

    template <typename U> 
    void one(); 
}; 

template <typename T> 
template <typename enable_if<is_pointer_t<T>::value>::type> 
void pointerOrNot<T>::one(){ 
    std::cout << "Success1" << std::endl; 
} 

template <typename T> 
template <typename enable_if<!is_pointer_t<T>::value>::type> 
void pointerOrNot<T>::one(){ 
    std::cout << "Success2" << std::endl; 
} 

, и он говорит, что не соответствует определению. Поэтому я пробовал:

template <typename T> 
class pointerOrNot{ 
public: 

    template <typename enable_if<is_pointer_t<T>::value>::type> 
    void one(); 
    template <typename enable_if<!is_pointer_t<T>::value>::type> 
    void one(); 
}; 

Но тогда один из одного() имеет пустой тип в качестве шаблона и компиляция не удалась. Как я могу это сделать? Также можно сделать это с помощью деструктора?

+1

Вместо выбор по политике уничтожения, я бы просто не принял никаких исходных указателей из-за проблемы собственности. Вы все равно можете использовать необработанные указатели, завернутые в объекты интеллектуального указателя, которые уничтожают или нет, в качестве выбора кода клиента. Нетрудно определить умный указатель, и это один из хороших способов полностью разделить проблемы **. –

+0

Если вам действительно нужен выбор по типу указателя против не указателя, тогда вы можете использовать шаблон вспомогательной функции, специализированный для is и is-not. Вы также можете использовать так называемый «основанный на политике дизайн», который по существу состоит в том, чтобы иметь шаблон P в качестве параметра шаблона, где P создается посредством, например, ваш Т и обеспечивает, например, уничтожение работа. Но вы получаете гораздо более простое и чистое разделение проблем с умными указателями. –

+0

Для «В моем скромном мнении» гораздо более читаемая альтернатива «enable_if», которую я называю просто «If_», см. (Https://github.com/alf-p-steinbach/cppx/blob/plutonium/core_language_support/tmp/ If_.hpp). –

ответ

1

Сначала давайте рассмотрим следующий класс для указателей:

template <typename T> 
struct Introducer{ 

    void intro(){ 
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl; 
    } 

    T mem; 
    Introducer(T m):mem(m){} 
}; 

он отлично работает с указателями, но он также работает с не-указатели:

Introducer<int> i(10); 
    i.intro();//just fine! 

Мы хотели бы обнаружить это злоупотребление во время время компиляции, также мы меняем Индуктор до

Теперь компилятор не позволяет нам использовать указатель без указателя. На следующем этапе мы хотели бы иметь специальную функцию для не-указателей с помощью SFINAE:

template <typename T> 
struct Introducer{ 
    typename enable_if<is_pointer_t<T>::value, void>::type 
    intro(){ 
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl; 
    } 

    typename enable_if<!is_pointer_t<T>::value, void>::type 
    intro(){ 
    std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl; 
    } 

    ... 
}; 

Черт, это даже не компилируется! Позволяет прочитать отрывок о SFINAE более тщательно:

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

T не в непосредственной связи и, таким образом, SFINAE не работает, позволяет привести T в непосредственный контекст:

template <typename T> 
struct Introducer{ 

    template <typename C=T> 
    typename enable_if<is_pointer_t<C>::value, void>::type 
    intro(){ 
    std::cout<<"I'm a pointer, I point to adress "<<mem<<std::endl; 
    } 


    template <typename C=T> 
    typename enable_if<!is_pointer_t<C>::value, void>::type 
    intro(){ 
    std::cout<<"I'm a non-pointer, my value is "<<mem<<std::endl; 
    } 

    ... 
}; 

теперь программа

int main(){ 
    Introducer<float*> fp(NULL); 
    fp.intro(); 

    //But this works also: 
    Introducer<int> i(10); 
    i.intro(); 
} 

результаты:

I'm a pointer, I point to adress 0 
I'm a non-pointer, my value is 10 

Как насчет деструктора? Проще всего было бы назвать SFINAE уничтожения, функции из деструктора (я никогда не видел SFINAE-деструкторов и не будет знать, как писать один, но это ничего не значит):

template <typename T> 
struct Introducer{ 
    ... 

    ~Introducer(){ 
    intro(); 
    std::cout<<"and I'm deleted..."<<std::endl; 
    } 
}; 

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

  • Нет связанных вопросов^_^