специализирующие функции на типах контейнеров в стиле stl - PullRequest
3 голосов
/ 15 декабря 2009

Если у меня есть тип T, какой полезный способ проверить его во время компиляции, чтобы увидеть, является ли он контейнером в стиле STL (для произвольного типа значения) или нет?
(Предположение: указатели, ссылки и т. Д. Уже удалены)

Стартовый код:

template<class T> // (1)
void f(T&) {} 

template<class T> // (2)
void f(std::vector<T>&) {} 

void test() 
{
    int a;
    std::vector<int> b;
    f(a);
    f(b);
}

Теперь это работает нормально, но что, если я хочу обобщить контейнер (т.е. не определять (3) , (4) , ... явно)?

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

В качестве идентификатора я не могу использовать итераторы - я пытаюсь специализироваться на основе функций, которые получают T s в качестве параметров.


Согласно MSalters ответ :

template<class T>
void f(T&, ...) {
    std::cout << "flat" << std::endl; 
}

template<class Cont>
void f(Cont& c, typename Cont::iterator begin = Cont().begin(),
                typename Cont::iterator end   = Cont().end()) {
    std::cout << "container" << std::endl; 
}

(Переменный список аргументов необходим, чтобы первая f была наименее предпочтительной версией для решения ошибок неоднозначности)

Ответы [ 3 ]

2 голосов
/ 15 декабря 2009

Все, что вы делаете, почти наверняка будет чрезвычайно хрупким. Там просто нет четкой разделительной линии между тем, что является или не является "STL". Даже если бы была четкая разделительная линия, это почти наверняка было бы очень плохой основой для такого решения в любом случае. Например, если я напишу (или использую) повторную реализацию std :: map, использующую дерево AVL вместо более распространенного дерева R-B, почему он должен трактоваться иначе, чем std :: map?

В случае хешированных контейнеров, существует целый прогресс от различных реализаций hash_map, к контейнерам Boost, к контейнерам TR1, к тем, которые будут включены в стандартную библиотеку в C ++ 0x. В зависимости от того, как вы определяете «STL», вполне вероятно, что, по крайней мере, один из них не является STL, а другой - нет, но не существует единственного момента, в котором, вероятно, имеет смысл рассматривать одно по-другому.

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

2 голосов
/ 15 декабря 2009
Контейнеры

STL по определению имеют typedef iterator, с 2 методами begin() и end(), которые их перезапускают Этот диапазон равен тому, что содержит контейнер. Если такого диапазона нет, это не контейнер в смысле STL. Таким образом, я бы предложил что-то вроде (не проверено)

template<typename CONTAINER>
void f(CONTAINER& c,
       typename CONTAINER::iterator begin = c.begin(),
       typename CONTAINER::iterator end = c.end())
{ }
0 голосов
/ 15 декабря 2009

Согласно www.cplusplus.com , единственными функциями, которые являются общими для всех контейнеров STL, являются:

  • Конструктор
  • operator=
  • size.

Во время компиляции вы можете определить, существуют ли эти операторы для вашего типа T.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...