шаблон класса, оператор друга << перегрузка - PullRequest
3 голосов
/ 10 ноября 2010

Я пытаюсь перегрузить оператор "<<" для шаблона класса.У меня есть определение класса в файле .h и его реализация в файле .cpp.</p>

/tmp/ccjJIJhO.o: In function `main':
main.cpp:(.text+0xad): undefined reference to `std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, FeatureVector<int>&)'
main.cpp:(.text+0xba): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, FeatureVector<int> const&)'
collect2: ld returned 1 exit status

Определение класса:

common.h

#include <iostream>
using namespace std;

featurevector.h

#ifndef FEATURE_VECTOR_H
#define FEATURE_VECTOR_H

#include <common.h>

template < class FEAT_TYPE >
class FeatureVector;

template < class FEAT_TYPE >
istream & operator >> (istream &, FeatureVector<FEAT_TYPE> &);

template < class FEAT_TYPE >
ostream & operator << (ostream &, const FeatureVector<FEAT_TYPE> &);

template < class FEAT_TYPE >
class FeatureVector{
    public:
        FeatureVector(int = 0);
        ...
        friend istream & operator >> <>(istream &, FeatureVector<FEAT_TYPE> & );
        friend ostream & operator << <>(ostream &, const FeatureVector<FEAT_TYPE> &);
        ...
        ~FeatureVector();

    private:
        int m_nDim;
        FEAT_TYPE * m_pFeat;
};
#endif

featurevector.cpp

#include <featurevector.h>
...
template < class FEAT_TYPE >
istream & operator >> (istream & input, FeatureVector< FEAT_TYPE> & refFeat ){

    int d;

    for(d=0; d < refFeat.getDim(); d++){
        input >> refFeat.m_pFeat[d];
    }

    return (input);
}

template < class FEAT_TYPE >
ostream & operator << (ostream & output, const FeatureVector< FEAT_TYPE > & refFeat ){

    int d;

    for(d=0; d < refFeat.getDim(); d++){
        output << refFeat.m_pFeat[d] << " ";
    }

    output << endl;

    return (output);
}
...
#include "featurevector-impl.cpp"

featurevector-impl.cpp

template class FeatureVector<int>;
//template istream & operator >> <>(istream &, FeatureVector<int> &);
//template ostream & operator << <>(ostream &, const FeatureVector<int> &);

mylib.h

#ifndef MY_LIB_H
#define MY_LIB_H
#include <featurevector.h>
#endif

main.cpp

#include <mylib.h>
#include <common.h>

int main(){
    FeatureVector<int> pFeat(10);
    cin >> (pFeat);
    cout << (pFeat);

    return (0);
}

Makefile, связанный с "mylib"

INC=./inc
SRC=./src
LIB=./lib
OBJ=./obj

CC=g++
CFLAGS=-O3 -Wall

mylib: $(LIB)/mylib.a
echo "mylib was created!..."

$(LIB)/mylib.a: \
$(OBJ)/featurevector.o 
    ar csr $(LIB)/mylib.a \
$(OBJ)/featurevector.o 

$(OBJ)/featurevector.o: $(SRC)/featurevector.cpp
    $(CC) -c $(CFLAGS) $(SRC)/featurevector.cpp -I$(INC)  \
    -o $(OBJ)/featurevector.o

clean:
    rm -rf $(LIB)/*.a
    rm -rf $(OBJ)/*.o

Makefile для main.cpp (main.cpp с его Makefile находится в каталоге "app")

LIB=../lib
INC=../inc
OBJ=../obj
BIN=../bin

CC=g++
CFLAGS=-O3 -Wall
LFLAGS=-lmylib -lm

$@.cpp: $(LIB)/mylib.a $@.cpp
    cd ..; make; cd app;
$(CC) $(CFLAGS) $@.cpp -o $(BIN)/$@ -I$(INC) -L$(LIB) $(LFLAGS)

clean:
    rm -rf $(BIN)/*

Ответы [ 5 ]

4 голосов
/ 05 апреля 2013

Согласно this , вы должны сделать функцию известной как шаблон в вашем определении класса.

class.h

#include <iostream>
using std::ostream;

template <typename T>
class A {
  public:
    ...

    template <typename J> // <-- CAUTION!
    friend ostream &operator<<(ostream &output, const A<J> &a);
};

class.cpp

#include "class.h"
...
template <typename T>
ostream &operator<<(ostream &output, const A<T> &a) {
  // Your implementation
  return output;
}

...
template ostream &operator<<(ostream &output, const A<int> &a);
template ostream &operator<<(ostream &output, const A<float> &a);

Если строка template <typename J> удалена, возникает ошибка компиляции «недоопределенная ссылка».

1 голос
/ 10 ноября 2010

Ваш опубликованный код ошибки говорит о том, что operator>> вызывает нерешенную внешнюю ошибку, а не operator<<.Кроме того, ваш код не будет компилироваться, потому что на myClass нет конструктора преобразования, принимающего int.Таким образом, вы не отправили правильный код.

Но это работает:

#include <iostream>
using namespace std;

template < class T >
class myClass;

template < class T >
ostream & operator << (ostream &, const myClass<T> &);

template < class T >
class myClass{
    public:
        myClass(int) {}
        friend ostream & operator << <>(ostream &, const myClass<T> &);

    private:
        T m_Data;
};

template < class T >
ostream & operator << (ostream & out, const myClass<T> & refClass){
    out << refClass.m_Data << endl;
    return (out);
}

myClass<int>;
myClass<float>;



int main(int argc, char **argv){
    myClass<int> test(5);
    cout << test;
    return 0;
}
0 голосов
/ 10 ноября 2010

Не усложняйте:

template<class FEAT_TYPE>
struct FeatureVector {
  FeatureVector(int = 0);

  friend std::istream& operator>>(std::istream &s, FeatureVector &x) {
    for(int d = 0; d < x.getDim(); d++) {
      s >> x.m_pFeat[d];
    }
    return s;
  }

  friend std::ostream& operator<<(std::ostream &s, FeatureVector const &x) {
    // since you're terminating with " " rather than separating:
    copy(x.m_pFeat, x.m_pFeat + x.getDim(), ostream_iterator<FEAT_TYPE>(s, " "));
    s << endl;
    return s;
  }

  //...
0 голосов
/ 10 ноября 2010

featurevector-impl.cpp неверен. Явные экземпляры шаблона выглядят так:

template class FeatureVector<int>;

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

template istream & operator >> <>(istream &, FeatureVector<int> &);

Я не рекомендую разбивать ваши определения шаблонов, как это, тем не менее, если вы действительно не заинтересованы в микроуправлении, какие конкретные классы будут работать с вашим шаблоном (что противоречит духу использования шаблона).

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