Использование SFINAE для разрешения члена-распределителя условно - PullRequest
0 голосов
/ 29 июня 2018

Я пишу конструктор для структуры данных списка.

template <class T, class Allocator = std::allocator<T>>
class list {

...
}

Класс принимает параметр шаблона Allocator и по умолчанию равен std::allocator, если ничего не указано. Поскольку распределители C ++ 11 могут иметь состояние, конструктор по умолчанию также принимает объект распределителя.

//    *** CONSTRUCTORS ***
explicit list(const Allocator& alloc = Allocator()): alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0) {
    if(std::is_same<Allocator, customAllocator<T>>::value) {
        std::cout << "****" << std::endl;
        std::cout << alloc.member_ << std::endl;
        std::cout << alloc_.member_ << std::endl;
        std::cout << "****" << std::endl;
    }
}

Когда предоставляется специальный распределитель, который содержит 'member_', следующие строки выполняются без сбоев.

Однако, когда передается std::allocator, компилятор понятно жалуется, что в распределителе нет члена member_.

Однако существует ли способ, чтобы строки std::cout печатались, когда предоставляется пользовательский распределитель, и не печатались, когда предоставляется std::allocator (или любой распределитель без 'member_')?

Спасибо

1 Ответ

0 голосов
/ 29 июня 2018

Ваша проблема - типичная проблема, для которой в C ++ 17 было введено if constexpr

 if constexpr (std::is_same<Allocator, customAllocator<T>>::value) {
    std::cout << "****" << std::endl;
    std::cout << alloc.member_ << std::endl;
    std::cout << alloc_.member_ << std::endl;
    std::cout << "****" << std::endl;
}

До C ++ 17 if constexpr недоступен, поэтому std::cout << alloc.member_ компилируется также, когда тест std::is_same имеет значение false.

Таким образом, вы должны каким-то образом разработать две разные функции: одну для customAllocator и одну для других.

Полагаю, вы можете попробовать что-то вроде следующего (осторожно: код не проверен)

   template <typename T>
   void printMember (customAllocator<T> const & a)
    { 
      std::cout << "****" << std::endl;
      std::cout << alloc.member_ << std::endl;
      std::cout << alloc_.member_ << std::endl;
      std::cout << "****" << std::endl;
    }

   template <typename A>
   void printMember (A const &)
    { }

   explicit list(const Allocator& alloc = Allocator())
      : alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0)
    { printMember(alloc); }

При желании вы также можете написать функцию для распределителей с member_ членом и одну для других.

Что-то следующее (осторожно: код не проверен)

   template <typename A>
   auto printMember (A const & a, int)
      -> decltype( a.member_, void() )
    { 
      std::cout << "****" << std::endl;
      std::cout << alloc.member_ << std::endl;
      std::cout << alloc_.member_ << std::endl;
      std::cout << "****" << std::endl;
    }

   template <typename A>
   void printMember (A const &, long)
    { }

   explicit list(const Allocator& alloc = Allocator())
      : alloc_(alloc), head_(nullptr), tail_(nullptr), size_(0)
    { printMember(alloc, 0); }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...