0

I've recently been tasked at work to try to migrate a C++ project from its old Windws 2003 server to a Windows 2008. For the moment, I am trying to build the application locally, on my Windows 7PC. I've followed an installation guide that I've received. Things seem to have worked quite well. The problem that I'm having is that, after the compilation step, the linker is giving me the following error:

msvcprtd.lib(MSVCP90D.dll) : error LNK2005: "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl std::operator<<<struct std::char_traits<char> >(class std::basic_ostream<char,struct std::char_traits<char> > &,char const *)" (??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z) already defined in CellSortTypeIds.obj

This is run in the debug mode, by the way. In the release mode, I am getting the same error. I can show you the corresponding CPP file:

  1. CellSortTypeIds.h file:

    #ifndef CELL_SORT_TYPE_IDS_H
    #define CELL_SORT_TYPE_IDS_H
    
    #include <iostream>
    
    #include <QtCore/QString>
    
    namespace CellSortTypeIds
    {
        enum CellSortTypeEnum 
        {
            NAME=0, LAC, CI, NB_ITEMS
        };
    
        static const QString mStrings[] = 
        {
            QT_TR_NOOP("Tri par code Nom"), QT_TR_NOOP("Tri par code LAC"), QT_TR_NOOP("Tri par code CI")
        };
    
        QString getQString(const CellSortTypeIds::CellSortTypeEnum aCellSortType);
    
        CellSortTypeEnum getCellSortTypeFromQString( QString aCellSortType );
    }
    
    std::ostream& operator <<(std::ostream &, const CellSortTypeIds::CellSortTypeEnum&); 
    
    #endif //CELL_SORT_TYPE_IDS_H
    
  2. CellSortTypeIds.cpp file

    #include "CellSortTypeIds.h"
    #include <QtCore/QObject>
    
    using namespace std;
    
     ostream& operator <<(ostream &out, const CellSortTypeIds::CellSortTypeEnum& aCellSortType)
    {
        out << CellSortTypeIds::getQString(aCellSortType).toAscii().operator const char*();
        return out;
    } 
    
    QString CellSortTypeIds::getQString(const CellSortTypeIds::CellSortTypeEnum aCellSortType)
    {
        QString result("");
    
        if( aCellSortType < CellSortTypeIds::NB_ITEMS )
        {
            result = QObject::tr( CellSortTypeIds::mStrings[aCellSortType].toAscii().data() );
        }
        else
        {
            cerr << __FILE__<< "(" <<__LINE__ << "): mStrings[" << (int)aCellSortType << "] not initialised" << endl;
        }
    
        return result;
    }
    
    CellSortTypeIds::CellSortTypeEnum CellSortTypeIds::getCellSortTypeFromQString( QString aCellSortTypeString )
    {
        CellSortTypeIds::CellSortTypeEnum theEnum( CellSortTypeIds::NAME );
        bool found( false );
    
        for( int index( 0) ; index < CellSortTypeIds::NB_ITEMS && !found ; index++ )
        {
            if( QObject::tr(CellSortTypeIds::mStrings[ index ].toAscii().data()) == aCellSortTypeString )
            {
                theEnum = (CellSortTypeIds::CellSortTypeEnum)index;
                found = true;
            }
        }
    
        return theEnum;
    }
    

My C++ knowledge is not that good. I've read several posts on SO regarding this issue, some telling about the configured runtime, some about not defining operators in the header files, but putting them in the cpp file. Here I believe it is not the case.

My suspicion is that there's an issue in these two files that I can't figure out. Any idea is appreciated. Let me know if you need any more details. Thank you in advance, and please don't hesitate to give any feedback on the structure of the question, since it is my first question, after all.

  • @BoPersson Given that they got an installation guide for it, I don't think that the asker wrote the code. Right now they are just trying to build it. – Max Langhof Jul 05 '18 at 15:07
  • Does the linker error still appear if you simply comment out all stream operations in the `.cpp`? If not, which ones cause it? – Max Langhof Jul 05 '18 at 15:10
  • @BoPersson Max is correct, I have not given much thought to the content of the project just yet, since the main objective is to get it to run on a newer machine. However, according to https://stackoverflow.com/questions/18693866/how-to-interpret-operator-const-char-in-operator-overloading, .operator const char* is a cast to a String, such as calling .c_str() – Radu Cristian Neagoe Jul 05 '18 at 15:11
  • Thank you for your implication so far. I've commented the stream operations as Max has suggested (including cerr << __FILE__<< "(" <<__LINE__ << "): mStrings[" << (int)aCellSortType << "] not initialised" << endl; which I had not done before). The error has shifted to another file which has a very similar definition of this operator. I have commented the streaming operations there as well and now I am rebuilding. – Radu Cristian Neagoe Jul 05 '18 at 15:32
  • 1
    Anyway replace .toAscii() with .toLatin1() because that does same with accurate name and consider moving to .toUtf8() that is what people usually want to have in long run. The .operator const char*() can be replaced with .constData() that is less obscure equivalent of .c_str() in Qt. – Öö Tiib Jul 05 '18 at 15:50
  • I'm curious if changing enum definition to enum **class** CellSortTypeEnum will do the trick – wtom Jul 05 '18 at 16:07
  • 1
    Related to the template generation method? A few methods to instantiate template instances, do not play nicely together. Not sure about VS. If you are in the middle of debugging the build process sometimes clean clears out issues. The compiler linker can build lists of where particular instances are instantiated and these can get messed up. If you already have an instance instantiated in a library I am not sure how you get the linker/compiler to not make another. You may be able to use a methodology that uses weak symbols. It will duplicate instances but only use one at link time. – William J Bagshaw Jul 05 '18 at 16:14

1 Answers1

0

I would like to thank everyone for posting their thoughts/experience. After uninstalling Visual C++ 2005 as well as its distributable package, I no longer have this issue. I believe there was probably some interference caused by this installation (perhaps throught the system variables as well). The build runs and the ancient application is revived. Have a great weekend!