Main Page | Report this Page
.NET DotNet Forum Index  »  Visual C++ Forum  »  Please help, how do I fix error C4346 with the code...
Page 1 of 1    

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

Author Message
Jeff Chang...
Posted: Sun Oct 25, 2009 2:32 pm
Guest
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(1Cool );
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...
Posted: Mon Oct 26, 2009 6:59 am
Guest
Jeff Chang wrote:
Quote:
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(1Cool );
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;
}

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]...
Posted: Mon Oct 26, 2009 11:03 am
Guest
Quote:
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;

Quote:

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

microsoft.public.vc.language

Right. Cross-posting my comments there.
 
David Wilkinson...
Posted: Mon Oct 26, 2009 11:34 am
Guest
Ben Voigt [C++ MVP] wrote:
Quote:
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.

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 Smile.

--
David Wilkinson
Visual C++ MVP
 
Ben Voigt [C++ MVP]...
Posted: Mon Oct 26, 2009 11:41 am
Guest
"David Wilkinson" <no-reply at (no spam) effisols.com> wrote in message
news:u8VjCKmVKHA.220 at (no spam) TK2MSFTNGP02.phx.gbl...
Quote:
Ben Voigt [C++ MVP] wrote:
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.

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 Smile.

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?

Quote:

--
David Wilkinson
Visual C++ MVP
 
David Wilkinson...
Posted: Mon Oct 26, 2009 12:00 pm
Guest
Ben Voigt [C++ MVP] wrote:
Quote:
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 Smile.

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?

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.

--
David Wilkinson
Visual C++ MVP
 
Jeff Chang...
Posted: Tue Oct 27, 2009 3:29 pm
Guest
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]" <bvoigt at (no spam) newsgroup.nospam> wrote in message
news:82051108-F8AD-4832-A14E-060105CA0DE1 at (no spam) microsoft.com...
Quote:
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.

 
Giovanni Dicanio...
Posted: Sun Nov 08, 2009 1:56 pm
Guest
"Jeff Chang" <cpmame at (no spam) hotmail.com> ha scritto nel messaggio
news:065D01A9-0582-4345-BEFA-CA9027885534 at (no spam) microsoft.com...

Quote:
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...
Posted: Mon Nov 09, 2009 12:56 am
Guest
Giovanni Dicanio wrote:
Quote:
"Jeff Chang" <cpmame at (no spam) hotmail.com> ha scritto nel messaggio
news:065D01A9-0582-4345-BEFA-CA9027885534 at (no spam) 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

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.
 
 
Page 1 of 1    
All times are GMT - 5 Hours
The time now is Sat Nov 28, 2009 7:01 am