Некоторые ошибки компилятора, касающиеся перегруженного оператора в шаблоне в c ++ - PullRequest
0 голосов
/ 28 октября 2010

У меня есть код с несколькими ошибками, я не понимаю, как исправить вообще.Я спросил своего профессора и ТА, и безуспешно советовался с интернетом, не считая более точного понимания того, что означают ошибки.Насколько я могу судить, компилятор либо путает мой перегруженный оператор со встроенными операторами, либо вообще не распознает его как перегруженный оператор.

Я получаю следующие ошибки и предупреждения:

|| === Проект 4, Отладка === |\ project 4 \ forest.h | 13 | предупреждение: объявление друга 'Forest & operator + (Forest &, Forest &)' объявляет не шаблонную функцию |

\ project 4 \ forest.h | 13 | note: (ifэто не то, что вы хотели, убедитесь, что шаблон функции уже объявлен и добавьте <> после имени функции здесь) |

\ project 4 \ forest.h | 14 | предупреждение: объявление друга 'std:: ostream & operator << (std :: ostream &, const Forest &) 'объявляет не шаблонную функцию | </p>

\ project 4 \ forest.h | 15 | предупреждение: объявление друга' std :: istream & operator >>(std :: istream &, Forest &) 'объявляет не шаблонную функцию |

\ project 4 \ main.cpp || В функции' int main () ': |\ project 4 \ main.cpp | 21 | ошибка: неоднозначная перегрузка для 'operator >>' в 'файле >> intForest' |

c: \ программные файлы (x86) \ codeblocks \ mingw \ bin ..\ lib \ gcc \ mingw32 \ 4.4.1 \ include \ c ++ \ istream | 119 | примечание: кандидаты: std :: basic_istream <_CharT, _Traits> & std :: basic_istream <_CharT, _Traits> :: operator >> (std:: basic_istream <_CharT, _Traits> & (*) (std :: basic_istream <_CharT, _Traits> &)) [с _CharT = char, _Traits = std :: char_traits] |

c: \ программные файлы(x86) \ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ c ++ \ istream | 123 | note: std :: basic_istream <_CharT, _Traits> & std :: basic_istream <_CharT, _Traits> :: operator >> (std :: basic_ios <_CharT, _Traits> & (*) (std :: basic_ios <_CharT, _Traits> &)) [with _CharT = char, _Traits = std :: char_traits] |

c: \ program files (x86) \ codeblocks \ mingw \ bin .. \ lib \ gcc \ mingw32 \ 4.4.1 \ include \ c ++ \ istream | 130 | note: std :: basic_istream <_CharT, _Traits> &std :: basic_istream <_CharT, _Traits> :: operator >> (std :: ios_base & (*) (std :: ios_base &)) [with _CharT = char, _Traits = std :: char_traits] ||| === Сборка завершена: 1 ошибка, 3 предупреждения === |

Когда я пытаюсь скомпилировать свой код.Соответствующие сегменты кода:

(в файле forest.h)

template< typename NODETYPE > class Forest
{

    public:
        friend Forest<NODETYPE>& operator+(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<<(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

        ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};

(в файле forest.cpp)

template<typename NODETYPE> istream& operator>>(istream& file, const Forest<NODETYPE>& f1)
{
    istream file2 = file;
    int nodeCount = 0;
    string blah = ' ';

    while(getline(file2,blah))
    {
        nodeCount++;
    }

    ForestNode<NODETYPE> *forestNodeArray[nodeCount];//holds pointers to last node of depth i

    getline(file,*f1.root.tag);
    forestNodeArray[0] = &(*f1.root);
    inputHelper(file, 0, *f1.root, forestNodeArray, nodeCount);

    return file;
}

(и, наконец, в основном.cpp)

int main()
{

    Forest < char > intForest();
    filebuf fb;
    fb.open ("forest1.txt",ios::in);
    istream file(&fb);


    cout << typeid(intForest).name() << endl;
    cout << typeid(file).name() << endl;

    file >> intForest;

    fb.close();


}

Любая помощь будет принята с благодарностью.

РЕДАКТИРОВАТЬ: Спасибо alex и alf, я понимаю, почему они не считались шаблонными функциями.В ретроспективе это совершенно очевидно, я просто поставил эти подписи.Во всяком случае, я все еще получаю ошибку о неоднозначном операторе.Почему компилятор не распознает мой оператор и не использует его, вместо того чтобы пытаться выбрать между 3 встроенными версиями оператора, которые не могут иметь один параметр в виде Forest?

Ответы [ 3 ]

1 голос
/ 28 октября 2010

Вторая ошибка в этой строке:

Forest < char > intForest();

Поначалу это может удивлять, но эта строка не объявляет переменную типа Forest<char>, а скорее функцию, которая не принимает аргументов и возвращает Forest<char>. Просто удалите скобки из объявления:

Forest < char > intForest;

В первом предупреждении, которое уже объяснено (функция, объявленная в качестве друга, не является шаблоном, и это означает, что вам придется вручную применять его для каждого типа, который вы используете для создания экземпляра Forest<> с помощью (вероятно, вы не не хочу этого). Также обратите внимание, что объявление шаблонного operator+, а затем создание шаблона в качестве друга, как в ответе @Alf P. Steinbach, означает, что Forest<int> будет другом Forest<double>, что может быть вам нужно. @Alex предложение в комментарии только сделает конкретную реализацию шаблона другом, что, вероятно, ближе к тому, что вы хотите, но вам нужно объявить шаблонный оператор перед классом шаблона, и для этого вам потребуется вперед объявляем шаблон класса ...

Общий шаблон для функций, свободных от друзей, в шаблонах определяет функцию на месте:

template <typename T>
class Forest {
   // ...
   friend Forest& operator+( Forest const & lhs, Forest const & rhs ) [1]
   {
       // implementation here
   }
}
// [1] Note that the arguments are const references (read only), and also note that
//     you do not need to provide the type argument inside the template declaration

Это позволяет вам определить ее как не шаблонную функцию и в то же время сделать так, чтобы компилятор создавал ее для вас. Кроме того, обычно проще определить методы-члены, встроенные в определение класса при работе с шаблонами. Это упрощает жизнь, и, в конце концов, в большинстве случаев вам нужно предоставить реализацию в (том же самом) заголовочном файле.

Тем не менее, при определении бинарных операторов лучшим подходом является определение operator+= в качестве метода-члена, а затем вы можете легко определить operator+ как функцию, не являющуюся другом. Шаблон будет:

struct test {
   test& operator+=( test const & );
};
test operator+( test lhs, test const & rhs ) { // [2]
   lhs += rhs;
   return lhs;
}
// [2] Note that the first argument is by value, and the second by const reference
//     This means that the compiler will copy the first argument for you, and you
//     are free to modify it with the += operator and return the copy.

Теперь самое сложное - это смешать два предыдущих совета. Чтобы иметь возможность определить operator+, которая является свободной функцией внутри определения шаблона, обычная хитрость заключается в том, чтобы сделать ее дружественной, даже если это не требуется по причинам доступа:

template <typename T>
class Forest {
   Forest& operator+=( Forest const & ) {
      // implemenation
   }
   friend Forest operator+( Forest lhs, Forest const & rhs ) { // [3]
      return lhs+=rhs;
   }
};
// [3] friendship only to allow us to define the free function inside the template
//     declaration.
0 голосов
/ 09 апреля 2013

изучая C ++, я также столкнулся с той же проблемой. Но я решил ее по-другому!

template <class NODETYPE> class Forest;
template <class NODETYPE> Forest<NODETYPE>& operator+ (Forest<NODETYPE>&, Forest<NODETYPE>&);
template <class NODETYPE> ostream& operator<<(ostream&, const Forest<NODETYPE>&);
template <class NODETYPE>  istream& operator>> (istream&, Forest<NODETYPE>&);
template<class NODETYPE>
template< typename NODETYPE >
class Forest
{

    public:
        friend Forest<NODETYPE>& operator+ <>(Forest<NODETYPE>&, Forest<NODETYPE>&);
        friend ostream& operator<< <>(ostream&, const Forest<NODETYPE>&);
        friend istream& operator>> <>(istream&, Forest<NODETYPE>&);

        Forest();
        Forest( const Forest& otherForest);
        ~Forest();
        void nodes(int&) const;

    private:
        ForestNode<NODETYPE> *root;

        ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};
0 голосов
/ 28 октября 2010

(Первое) предупреждение говорит о том, что подружившаяся функция не является шаблоном.

И это не так.

Подумайте, как бы вы это реализовали. Это повлечет за собой написание одной такой функции для каждого возможного NODE_TYPE.

Есть несколько способов исправить это.

Один из способов - подружиться с шаблоном функции, например:

template< class Type >
struct S
{
    template< class U > friend void foo( S<U> );
};

template< class Type >
void foo( S< Type > x ) {}

int main()
{}

Приветствия & hth.,

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