如何声明模板的友元函数的特化

时间:2014-02-15 05:36:55

标签: c++ templates c++11 friend-class

拥有模板:

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;
};

我有运营商&lt;&lt;作为朋友班:

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;

运营商的一般形式&lt;&lt;被称为而不是我的专业化。我想我并没有特别专注。有关如何声明朋友类专业化的任何帮助吗?

根据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;
}

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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