2014-02-15 2 views
1

Имея шаблон:Как объявить специализацию друг функции шаблона используйте в

template <typename T, template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont=std::vector> 
class VehiclesContainer { 
    public: 
    VehiclesContainer(std::initializer_list<T> l):container(l){}; 
    virtual ~VehiclesContainer(){}; 
    virtual void addVehicle(T elem); 
    virtual T getFirst() const; 
    template 
    <typename U, template <typename ELEM2, typename ALLOC=std::allocator<ELEM2> > class Cont2> 
    friend std::ostream& operator<<(std::ostream& out, const VehiclesContainer<U,Cont2>& obj); 
    private: 
    Cont<T> container; 
}; 

У меня есть оператор < < как друг класс:

template 
<typename T,template <typename ELEM,typename ALOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator<<(std::ostream& out,const VehiclesContainer<T,Cont>& obj){ 
    typename Cont<T>::const_iterator it; 
    for(it=obj.container.begin(); it!=obj.container.end(); ++it) 
     out << *it << " "; 
    return out; 
} 

То, что я хочу сделать, это иметь специализация для этой функции для целых чисел, в которой вместо пространства будет - между элементами на выходе. Я попытался

template 
<int,template <typename ELEM,typename ALOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator<<(std::ostream& out,const VehiclesContainer<int,Cont>& obj){ 
    typename Cont<int>::const_iterator it; 
    for(it=obj.container.begin(); it!=obj.container.end(); ++it) 
     out << *it << "-"; 
    return out; 
} 

Но когда я компилирую, имея в главном

VehiclesContainer<int,std::vector > aStack1({10,20,30}); 
std::cout << aStack1; 

Общий вид оператора < < вызывается вместо моей специализации. Я полагаю, что я действительно не специализировался. Любая помощь в том, как можно объявить специализацию для класса друзей?

Решение на основе ответа WhozCraig

вперед заявление:

template <typename T, template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont=std::vector> 
class VehiclesContainer; 

template <typename T, template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator<< (std::ostream& out, const VehiclesContainer<T,Cont>& obj); 

template <template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator<< (std::ostream& out, const VehiclesContainer<int,Cont>& obj); 

Декларация внутри класса:

friend std::ostream& operator << <T,Cont>(std::ostream&, 
       const VehiclesContainer<T,Cont>&); 

friend std::ostream& operator << <Cont>(std::ostream&, 
       const VehiclesContainer<int,Cont>&); 

Определение функций друга:

template <typename T, template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator <<(std::ostream& os, const VehiclesContainer<T,Cont>& obj) 
{ 
    if (obj.container.size() > 0) 
    { 
     os << obj.container.front(); 
     for (auto it = std::next(obj.container.begin()); it != obj.container.end(); ++it) 
      os << ' ' << *it; 
    } 
    return os; 
} 

template <template <typename ELEM, typename ALLOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator << (std::ostream& os, const VehiclesContainer<int,Cont>& obj) 
{ 
    if (obj.container.size() > 0) 
    { 
     os << obj.container.front(); 
     for (auto it = std::next(obj.container.begin()); it != obj.container.end(); ++it) 
      os << '-' << *it; 
    } 
    return os; 
} 

ответ

0

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

#include <iostream> 
#include <vector> 
#include <cstdlib> 

// forward declaration of template class 
template <class T, template<class, class...> class Cont = std::vector, class... Args> 
class VehiclesContainer; 

// generic template for all T and all container types 
template<class T, template<class, class...> class Cont = std::vector, class... Args> 
std::ostream& operator <<(std::ostream&, const VehiclesContainer<T,Cont,Args...>&); 

// specific template for only int and all container types 
template<template<class, class...> class Cont = std::vector, class... Args> 
std::ostream& operator << (std::ostream& os, const VehiclesContainer<int,Cont,Args...>& obj); 


template <class T, template<class, class...> class Cont, class... Args> 
class VehiclesContainer 
{ 
public: 
    VehiclesContainer(std::initializer_list<T> l) 
     : container(l) 
    {}; 

    // friend overloaded to `int` type 
    friend std::ostream& operator << <T,Cont,Args...>(std::ostream&, 
       const VehiclesContainer<T,Cont,Args...>&); 

    friend std::ostream& operator << <Cont, Args...>(std::ostream&, 
       const VehiclesContainer<int,Cont,Args...>&); 

private: 
    Cont<T,Args...> container; 
}; 

template<class T, template<class, class...> class Cont, class... Args> 
std::ostream& operator <<(std::ostream& os, const VehiclesContainer<T,Cont,Args...>& obj) 
{ 
    if (obj.container.size() > 0) 
    { 
     os << obj.container.front(); 
     for (auto it = std::next(obj.container.begin()); it != obj.container.end(); ++it) 
      os << ' ' << *it; 
    } 
    return os; 
} 

template<template<class, class...> class Cont, class... Args> 
std::ostream& operator << (std::ostream& os, const VehiclesContainer<int,Cont,Args...>& obj) 
{ 
    if (obj.container.size() > 0) 
    { 
     os << obj.container.front(); 
     for (auto it = std::next(obj.container.begin()); it != obj.container.end(); ++it) 
      os << '-' << *it; 
    } 
    return os; 
} 


int main() 
{ 
    VehiclesContainer<std::string> vcString { "Camero", "Corvette" }; 
    VehiclesContainer<int> vcInt { 1,2,3 }; 

    std::cout << vcString << '\n'; 
    std::cout << vcInt << '\n'; 

    return 0; 
} 

Выход

Camero Corvette 
1-2-3 
+0

Я попытался сделать что-то подобное, имея общий 'friend std :: ostream & operator << (std :: ostream & out, const VehiclesContainer & obj)' и 'friend std :: ostream & operator << (std :: ostream & out , const VehiclesContainer & obj) 'как встроенный. Но компилятор жалуется на переопределение. –

+0

@Avraam Какой компилятор, если вы не возражаете против моего запроса? Вышеупомянутый стенограмм не работает для вас? – WhozCraig

+0

Я использую g ++ в Windows с wingw, я не пытаюсь точно указать ваш код, я просто объявляю два встроенных оператора '<< <<, как вы это делали (опуская переменные) только для теста, но компилятор жалуется на переопределение. Я попробую ваш код и сообщу вам. Спасибо. –

0

Я думаю, что правильный способ сделать это заключается в следующем:

template 
<template <typename ELEM2, typename ALLOC=std::allocator<ELEM2> > class Cont2> 
friend std::ostream& operator<<(std::ostream& out, const VehiclesContainer<int,Cont2>& obj); 

Вы должны сделать это перед другим объявлением в противном случае это будет частным конечно.

template 
<template <typename ELEM,typename ALOC=std::allocator<ELEM> > class Cont> 
std::ostream& operator<<(std::ostream& out,const VehiclesContainer<int,Cont>& obj){ 
    typename Cont<int>::const_iterator it; 
    for(it=obj.container.begin(); it!=obj.container.end(); ++it) 
     out << *it << "-"; 
    return out; 
} 
+0

Я уже пробовал и не компиляции. Существует целый список ошибок компиляции. –

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