Error C2275 caused by template member function. Is this code wrong? - c++

I think I've run into a (possible) VC6 (I know. It's what we use.) compiler error, but am open to the fact that I've just missed something dumb. Given the following code (It's just an example!):
#include <iostream>
// Class with template member function:
class SomeClass
{
public:
SomeClass() {};
template<class T>
T getItem()
{
return T();
};
};
// Dummy just used to recreate compiler error
class OtherClass
{
public:
OtherClass() {};
};
std::ostream& operator<<( std::ostream& oStr, const OtherClass& obj )
{
return oStr << "OtherClass!";
};
// Main illustrates the error:
int main(int argc, char* argv[])
{
SomeClass a;
OtherClass inst2 = a.getItem<OtherClass>(); // Error C2275 happens here!
std::cout << inst2 << std::endl;
return 0;
}
If I try to compile this code VC6, dies on a.getItem<OtherClass>() yielding:
Error C2275: 'OtherClass' : illegal use of this type as an expression.
Have I overlooked some trivial syntax issue? Am I breaking a rule?
This code compiles just fine under gcc 4.3.4. Is it yet another compliance issue with VC6?
Thanks!

Among many other things with the word template in it, VC6 couldn't deal with function templates where the template parameters aren't also function parameters. The common workaround was to add a dummy function parameter:
template<class T>
T getItem(T* /*dummy*/ = NULL)
{
return T();
} // note: no ; after function definitions
However, in general, VC6 is pretty lame and often chokes as soon as a TU contains the template keyword. I had to beat my head against it for several years (big code base compiled with several compilers/compiler versions; VC6 giving us an endless amount of trouble) and was very glad when I got rid of it in 2003.

This is likely to be a VC6 issue. Although VC6 compiles most basic templates correctly it is known to have many issues when you start to move towards the more advanced template uses. Member templates are an area where VC6 is known to be weak on conformance.

I believe that's another bug in VC6, you should really switch to a more up-to-date compiler.

Related

function template won't compile in VS2019 express

I have a project with quite a lot of function templates that I wrote back in Visual Studio 2017, and it always worked fine. Now I have to build it in VS2019, because I need to include the lib in another project that is written in VS2019, and the thing won't build.
There is one function template it seems to take issue with, although it doesn't actually complain about the function itself. The compiler just says "identifier not found" when I invoke it in the code. The thing is there in the namespace, however, even InteliSense sees it and links to it without complaining. Just the compiler won't.
Here's the code in question:
// declaration
namespace Oparse
{
// lots of other functions, many of them templates
template <typename T> OpModel<T> *_ModelPtr(T *receiver) { return new OpModel<T>(receiver); };
}
// Invocation
namespace Oparse
{
template <class T, class U>
class OpModelFactory
: public OpNestable
{
public:
OpModelFactory<T, U>(vector<U*> &receiver) : OpNestable(OP_MODELFACTORY), receiver(receiver) {};
// other stuff
void Serialize(string key, stringstream &stream, unsigned int indents)
{
for (unsigned int i = 0; i < receiver.size(); ++i)
{
// check if the instances are really of the type of this OpModel, otherwise there may be duplicates between polymorphic factories populating the same receiver.
T *currentModel = dynamic_cast<T*>(receiver[i]);
if (currentModel != NULL)
{
OpModel<T> *parser = _ModelPtr<T>(currentModel); // <-- identifier not found
parser->Serialize(key, stream, indents);
delete parser;
}
}
};
private:
vector<U*> &receiver;
}
}
If I comment that invocation, the project builds, despite there being a whole lot more function templates declared right where this one is. I have no clue what to do to make the linker find it. Are there any Visual Studio wizzards who could give me a hint? I must honestly confess that I haven't used the IDE in years, and it's my first time in Visual Studio 2019...
Here's the complete output of the error. There's a second message to it, but I found it perfectly unhelpful:
1>D:\Orbiter_installs\Orbiter2016\Orbitersdk\Oparse\include\OpModel.h(138,27): error C3861: '_ModelPtr': identifier not found
1>D:\Orbiter_installs\Orbiter2016\Orbitersdk\Oparse\include\OpModel.h(152): message : see reference to class template instantiation 'Oparse::OpModelFactory<T,U>' being compiled
And no, there's not further message attached. I have seen similar messages that usually go on with "with ... $further information", but this is all I get.
There is a circular dependency problem.
In Oparse.h, you first include OpModel.h that requires_ModelPtr in implementation of Serialize , but_ModelPtr is only defined later in the header.
You need to forward declare the template method.
In OpModel.h, write this instead:
namespace Oparse
{
template<typename T> class OpModel;
template <typename T> OpModel<T>* _ModelPtr(T* receiver);
// Remaining of OpModel.h...
typedef map<string, pair<Oparse::OpValue*, vector<Oparse::OpValidator*>>> OpModelDef;
typedef vector<pair<Oparse::OpValue*, vector<Oparse::OpValidator*>>> OpValues;
...

Optional Parameters in VS2010 templitized class function

I have an odd issue in MSVS 2010. I have a class with a function that is templitized and contains an parameter with a default value.
In my header file:
typedef unsinged int data32
class myClass
{
private:
...
public:
...
template <typename T>
T* myF(data32);
}
...
template<typename T>
T* myClass::myF(data32 size = 1)
{
...
}
Ok, now in my main i have something like this:
int main()
{
myClass A;
data32* myInt = A.myF<data32>(100); // no complaints from pre-compiler
data32* myInt2 = A.myF<data32>(); // pre-compiler complains "Error: no instance of the function template "myClass::myF" matches the argument list"
}
I understand why it is unhappy as i do not have a function prototype defined for 'myF()' in the class, but shouldn't it know better? I thought the point of defaults were to make the parameters optional in the call. The code DOES compile and run just fine even thought the pre-compiler is unhappy and flags this as a problem.
Any thoughts??
Thanks!
There are bugs (false alarms) in the intellisense analyzer in VS 2010. And this seems like one of them. The analyzer used for intellisense is different from the actual parser used in compiler.

Compiler Robustness ... Naivete

I use Visual Studio Professional 2012. I pre-compiled a class (header and source) successfully. Days later, when compiling another class (for the moment header only) that is utilizing the previous one, the compiler caught a missing reference if(this != &rhs) and semicolon rhs.root = nullptr;.
Perhaps it is my naivete and lack of knowledge about how compilers work but I thought a compiler was robust to catch errors such as these. It appeared to me that only when a specific block of code was required did the compiler feel the need to check it.
I have read about just-in-time compilation and learned how assembly compilers perform a two-pass compilation with symbols first and then syntax. I have not taken a course in compiler construction at my university and I know such courses give great insight into parsers, etc.
The code section where it failed to catch the error is this move assignment operator:
Tree &operator=(Tree &&rhs)
{
if(this != rhs) <--------- no reference to the rhs
{
root = std::move(rhs.root);
rhs.root = nullptr <----------- no semicoln
}
return *this;
}
The errors were generated while compiling boost variant, as well as my visitor class member:
bool operator() (Tree<std::string>& tree) const {
return tree.load(tree);
}
as well as a host of other errors related to boost serialization. The fix was to, of course, correct the missing reference and semicolon but I want to understand why this was caught apparently only when the compiler needed to touch this code?
Is it a template class?
Because semantic analysis of templates makes only sense when they are instantiated. That is, if it is a template, the compiler should generate an error at the missing semicolon (syntactic error), but not at the == operator.
The following code compiles with g++:
template<typename T>
struct A {
void q(A &a) {
if (this == a) {}
}
};
int main(int argc, char **argv) {
A<int> x;
//x.q(x);
}
But doesn't compile when
x.q(x);
is uncommented.

Effective C++ Item 43 Know how to access names in templatized base classes

In Item 43 of the book, it is said that the code below will not compile.
My understanding is that, compilation error occurs when the method LoggingMsgSender::sendClearMsg is instaniated.
However, for the three compilers (VC 2005, gcc 4.4.1, and one for embeded device) I have tried.
None of them show any compilation error.
Are there any compiler which can show the error as mentioned in the book?
Any suggestions are welcome.
Thank you for your help.
(I have found a potential compiler bug in VC 2005 in my source related to this kind
of template base-class function call, that's why I want to the compilation error.
That's a long story...)
class CompanyX
{
public:
void sendClearText(){};
};
typedef int MsgInfo;
template<typename Company>
class MsgSender {
public:
void sendClear(const MsgInfo&)
{
Company c;
c.sendClearText();
}
};
template<typename Company>
class LoggingMsgSender : public MsgSender<Company> {
public:
void sendClearMsg(const MsgInfo& info)
{
sendClear( info ); // ERROR : will not compile despite clearly being in base class.
}
};
int main()
{
LoggingMsgSender<CompanyX> sender;
sender.sendClearMsg(1); // specialization of the method!!!
}
http://liveworkspace.org/code/273c71cd53111dd8c6aaa54e64c53548 for example. get an error. in this case in function sendClearMsg we should use this->sendClear(info); compiler is gcc 4.7.1. And so, now is 2012 year, why you use old compilers?

STLPort ambiguous copy constructor in VS2008 with smart pointer class

We've written a smart pointer class and have been using it with great success with the built-in Visual Studio STL implementation.
The problem is we've realized our performance bottlenecks are in the STL library in code ported from Linux (where the STL is significantly faster the way we're using it). So I'm trying to link in STLPort to see if it deals with our performance problems.
When using STLPort 5.2.1 however I get very strange build errors related to ambigous copy constructors. I've stripped it down to a 50 line C++ program
#include "stdafx.h"
#include <set>
using namespace std;
template<class T>
class CRefCountPtr
{
public:
CRefCountPtr(T* pT) : m_T(pT)
{
}
T** operator&()
{
return &m_T;
}
operator T*() const
{
return (T*)m_T;
}
bool operator< (T* pT) const
{
return m_T < pT;
}
T* m_T;
};
class Example
{
int example;
};
int _tmain(int argc, _TCHAR* argv[])
{
set< CRefCountPtr<Example> > blah;
Example ex;
blah.insert(&ex);
return 0;
}
The error I get back from VS2008SP1 is
stlport\stl\_tree.h(318) : error C2782: 'void stlp_std::_Copy_Construct(_Tp *,const _Tp &)' : template parameter '_Tp' is ambiguous
stlport\stl\_construct.h(130) : see declaration of 'stlp_std::_Copy_Construct'
could be 'CRefCountPtr<T>'
with
[
T=Example
]
or 'Example *'
.....
stlport_example.cpp(43) : see reference to class template instantiation 'stlp_std::set<_Key>' being compiled
with
[
_Key=CRefCountPtr<Example>
]
I'm kind of stuck at how to proceed here, anybody have any idea what's going on with this one?
It's actually your operator& that's causing ambiguity. In g++ the ambiguity is in destruct rather than construct but I assume it's a similar problem.
The compiler tries to take the address of your T to construct/destruct it, and gets back a T** instead of a CRefCountPtr<T>*, causing confusion.
I bet you could create your own specific allocator that knows how to deal with this (aka not a template) and get it to compile.
Probably better long term is to get rid of the operator& as it'll only cause confusion.