Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Please help, how do I fix error C4346 with the code here...

0 views
Skip to first unread message

Jeff Chang

unread,
Oct 25, 2009, 4:32:46 PM10/25/09
to
Hi all,

Below is the sample c++ code that cause error C4346 in vs-2009 pro. I have a
"Record" struct within the Database class, and has a "Retrive(int n)" member
function that return "Record*" type. If I have my implementation code
defined within the class then everything works fine. However if I put it
outside the class I get error C4346. I prefer to put the implementation code
outside the class to keep the code clean. Please help.


Thanks
Jeff

//---------------------------------------------------------------------------
#include <iostream>
#include <string>
using namespace std;
const int Maximum = 100;

//---------------------------------------------------------------------------
// Code-1: Database class definition, has a nested "Record" struct inside
//---------------------------------------------------------------------------
template<typename Object>
class Database {
public:
struct Record {
Object ID;
Record( Object a=Object() ) : ID(a) {}
};

private:
Record items[Maximum];

public:
int Count;
Database() : Count(0) { }

// the following declaration with Code-2 definition will
cause error C4346
Record* Retrieve(const int n);

// however if I replace the code above and those Code-2 with
this the error is gone
// Record* Retrieve(const int n) {
// return &items[n];
// }

void Add(const Record& d) {
if ( Count<Maximum ) items[Count++] = d;
}
};

//---------------------------------------------------------------------------
// Code-2: Retrieve() definition with the return type of "Record".
// Receive the following error when trying to compile
// warning C4346: 'Database<Object>::Record' : dependent name is not a
type
// 1> prefix with 'typename' to indicate a type
// error C2143: syntax error : missing ';' before
'Database<Object>::Retrieve'
// error C4430: missing type specifier - int assumed. Note: C++ does
not support default-int
// fatal error C1903: unable to recover from previous error(s);
stopping compilation
//---------------------------------------------------------------------------
template<typename Object>
Database<Object>::Record*
Database<Object>::Retrieve(const int n) {
return &items[n];
}


//---------------------------------------------------------------------------
// Main Driver
//---------------------------------------------------------------------------
int main(int argc, char* argv[]) {

typedef Database<int>::Record rec;
Database<int> lists;
lists.Add( rec(12) );
lists.Add( rec(13) );
lists.Add( rec(15) );
lists.Add( rec(18) );
lists.Add( rec(17) );

cout << "Record ID\n";
for(int i = 0; i < lists.Count; i++)
cout << lists.Retrieve(i)->ID << endl;

cout << endl;
system("pause");
return 0;
}


//---------------------------------------------------------------------------
// Program Output
//---------------------------------------------------------------------------
Record ID
12
13
15

Press any key to continue . . .

David Wilkinson

unread,
Oct 26, 2009, 8:59:01 AM10/26/09
to

Jeff:

The message tells you what to do:

template<typename Object>
typename Database<Object>::Record* // use typename


Database<Object>::Retrieve(const int n)
{
return &items[n];
}

That said, online Comeau compiles you code as is. (I have never really
understood when you need typename...).

BTW, a better place for standard (non .NET) C++ questions is

microsoft.public.vc.language

--
David Wilkinson
Visual C++ MVP

Ben Voigt [C++ MVP]

unread,
Oct 26, 2009, 1:03:27 PM10/26/09
to
> The message tells you what to do:
>
> template<typename Object>
> typename Database<Object>::Record* // use typename
> Database<Object>::Retrieve(const int n)
> {
> return &items[n];
> }
>
> That said, online Comeau compiles you code as is. (I have never really
> understood when you need typename...).

It's because you could have a specialization of Database in which Record
isn't a struct:

template<>
class Database<int> { void Record() { StartRecording(); } };

In the example given, there's no ambiguity, stuff just doesn't work if
Record isn't a type. But this line could either be a function call or a
cast:

Record(x);

This could either be declaration or multiplication (if Record was a
variable):

Record* p;

>
> BTW, a better place for standard (non .NET) C++ questions is
>
> microsoft.public.vc.language

Right. Cross-posting my comments there.

David Wilkinson

unread,
Oct 26, 2009, 1:34:03 PM10/26/09
to

Ben:

You think online Comeau is wrong to accept OP's original code? That would be bad
news, because Comeau is my operational definition of whether a piece of code is
correct or not :-).

Ben Voigt [C++ MVP]

unread,
Oct 26, 2009, 1:41:16 PM10/26/09
to

"David Wilkinson" <no-r...@effisols.com> wrote in message
news:u8VjCKm...@TK2MSFTNGP02.phx.gbl...

No, I think that in context, none of the non-typename uses could ever be
allowed (multiplication and casting are statements, and not allowed at file
or namespace scope).

And I misread your comment "never understood when you need typename" as "why
you need typename" and explained why it's needed sometimes. I don't see any
good reason that this should be one of those times (the when).

BTW, you did choose "force instantiation of all templates" when using
tryitout, right?

David Wilkinson

unread,
Oct 26, 2009, 2:00:41 PM10/26/09
to

Ben:

OK, I misread your post.

Yes, I did use "force instantiation of all templates" (it seems to be the default).

I understand that typename is sometimes needed to avoid ambiguity; it's just
that it's hard to figure out when that might be.

Jeff Chang

unread,
Oct 27, 2009, 5:29:28 PM10/27/09
to
Hi David,

Thanks for your help. I will try the non-DotNet group. I also found out
putting the "typename" up front fix the error message. By the way is this
ANSI standard or just VS-2008? My textbook (year 2004) sample didn't have
the "typename" in front.

Besides hope you could give me some advice. Is there any benefit switching
to .Net C++? I am interested in audio-visual programming in the long run.
Should I even consider C# or Java for the sack of productivity?

Thanks
Jeff


"Ben Voigt [C++ MVP]" <bvo...@newsgroup.nospam> wrote in message
news:82051108-F8AD-4832...@microsoft.com...

Giovanni Dicanio

unread,
Nov 8, 2009, 1:56:47 PM11/8/09
to
"Jeff Chang" <cpm...@hotmail.com> ha scritto nel messaggio
news:065D01A9-0582-4345...@microsoft.com...

> Besides hope you could give me some advice. Is there any benefit switching
> to .Net C++? I am interested in audio-visual programming in the long run.
> Should I even consider C# or Java for the sack of productivity?

With '.Net C++' you mean C++/CLI, don't you?
I think that C++/CLI is good as a bridging layer between native code and
managed code.
e.g. if you have some native C++ library and you want to use that from .NET
languages like C#, you could develop a thin C++/CLI layer to connect the
native C++ platform with the .NET managed platform.
But my impression is that C++/CLI is not a first class .NET language; for
example: if you want to build GUIs with WPF, you can use C# or VB.NET, but
not C++/CLI (at least, this is my understanding).
And I think that ASP.NET does not support C++/CLI (only C# or VB.NET).
So, if you want to build something in .NET, I would suggest to consider C#
or VB.NET (if you come from C++, you would prefer C#, because its syntax
looks more natural than VB.NET for someone with a C++/Java background).

About productivity, yes C# offers high productivity to the programmer.
But if you want something that is small and fast, C++ is the way to go.

Giovanni

Scot Brennecke

unread,
Nov 9, 2009, 12:56:16 AM11/9/09
to

Well, C++/CLI will compile to MSIL just as any other .NET language, so
once it's compiled, it is supported anywhere any .NET assembly might be.
However, I agree that C# would almost always be the better choice for
developing a WinForms or WPF application. You CAN do it with C++/CLI,
but the syntax and IDE just aren't as friendly.

0 new messages