0

***Solution provided by JVApen for this particular case. I had to inline the operator overloads in the item.h file because I wasn't using an implementation file.

I've created a project that has 2 header files. One for an item structure and the other for a list that uses the structure. I'm getting the following errors and I know if I wrap the structure header in the nameless namespace they'll go away, but what's the underlying cause and how can I avoid it in the future?

1>Project2.obj : error LNK2005: "class std::basic_istream > & __cdecl operator>>(class std::basic_istream > &,struct item &)" (??5@YAAAV?$basic_istream@DU?$char_traits@D@std@@@std@@AAV01@AAUitem@@@Z) already defined in linkedList.obj 1>Project2.obj : error LNK2005: "class std::basic_ostream > & __cdecl operator<<(class std::basic_ostream > &,struct item const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABUitem@@@Z) already defined in linkedList.obj

I did not create an implementation file for the struct, everything is prototyped and defined in the header file, is that what is causing it?

I've included the item.h into my linkedList.h as show below:

item.h

#pragma once

#include <iostream>
#include <iomanip>
#include <string>


struct item {
    std::string name;
    double price;
    int currentInv;
    int minInv;

    item(std::string name = "default", double price = 0,
        int currentInv = 0, int minInv = 0)
        : name(name), price(price), currentInv(currentInv), minInv(minInv)
    {}

    bool operator<(const item& rhs) {
        return (this->name < rhs.name);
    }

    bool operator>(const item& rhs) {
        return (this->name > rhs.name);
    }

    bool operator==(const item& rhs) {
        return (this->name == rhs.name);
    }

    bool operator<=(const item& rhs) {
        return ((this->name < rhs.name) || (this->name == rhs.name));
    }

    bool operator>=(const item& rhs) {
        return ((this->name > rhs.name) || (this->name == rhs.name));
    }
};

std::ostream& operator<<(std::ostream& out, const item& printMe) {
    out << std::fixed << std::setprecision(2);
    return (out << std::setw(31) << std::left << printMe.name << ' ' <<
        std::right << std::setw(6) << printMe.price << ' ' << std::setw(3) <<
        printMe.currentInv << ' ' << std::setw(3) << printMe.minInv);
}

std::istream& operator>>(std::istream& in, item& fillMe) {
    return (in >> fillMe.name >> fillMe.price >> fillMe.currentInv >>
        fillMe.minInv);
}

linkedList.h

#pragma once

#include "item.h"

class List {
private:
//--- Node Class
class node {
public:

//--- Node Variables

    item data{};                            // item struct
    node* next;                             // ptr to next node

//--- Node Constructors

    node()
        : next(NULL) {}
    node(item& data, node* ptr = NULL)
        : data(data), next(ptr) {};

};

//--- Class Variables
int mySize;                                 // list Size
node* first;                                // first node

public:

//--- List Constructors
List();                                     
List(List& original);                       // copy constructor

//--- List Destructor
~List();                                    // destructor

//--- List Overrides
List& operator=(const List rhs);            // = overload

//--- List Public Functions
bool empty();                               

int nodeCount();                            
int search(const std::string findMe);       // find a piece of data

void addItem(item& addme);                  // add node
void changeItem();                          // change an item
void display(std::ostream& out);            // print out
void displayReversed(std::ostream& out);    // reverse print
void remove(int index);                     // remove node at index
void fileOut(std::ostream out);             // end of program file

private:

//---List Private Functions
void addItemPrivate(item& addme, node* ptr);
};

std::ostream& operator<<(std::ostream& out, const List& outMe);
Spyste
  • 13
  • 2

2 Answers2

0

In C++ programming languages, #pragma once is a non-standard. Use alternative methode ifndef in your header file as below

item.h/////////////

#ifndef ITEM_H
#define ITEM_H
... contents of item.h
#endif /* !ITEM_H */


linkedList.h ////////////

#ifndef LINKEDLIST_H
#define LINKEDLIST_H
... contents of linkedList.h
#endif /* !LINKEDLIST_H */

Note: you must have at least one cpp file that includes linkedlist.h file. You do not require to move your implementation to cpp file. Just create one linkedlist.cpp file and include linkedlist.h file inside it.

user2641018
  • 108
  • 5
  • 1
    Whilst `#pragma once` isn't standardised it is supported in most if not all modern compilers and isn't the cause of the OP's problem – Alan Birtles Mar 12 '20 at 08:25
-1

#pragma once prevents an include file from being included multiple times by the same .cpp file.

However, it doesn't prevent it from being included again in another .cpp file. So, every .cpp file in your project that includes item.h is going to create an implementation of those two methods.

Most linkers are smart enough to ignore those duplicates for class methods, but your << and >> operators are not part of a class. Only solution I'm aware of is to put them into a .cpp file.

user4581301
  • 33,082
  • 7
  • 33
  • 54
Garr Godfrey
  • 8,257
  • 2
  • 25
  • 23
  • 3
    More than `Most linkers are smart enough to ignore those duplicates for class methods` the standard says that methods defined in a class are automatically marked inline – Alan Birtles Mar 12 '20 at 08:27