• 13
• 15
• 27
• 9
• 9

namespace issue

This topic is 3826 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hey all, I've narrowed down a compilation problem to the following case. It seems to be a namespace issue, as putting all in the global namespace fixes the problem. Any ideas? Maybe my namespace+template understanding isn't as solid as I once thought?
namespace NSbase
{
namespace NSone
{
struct FooStruct
{
int a,b,c;
};

template <unsigned int A,unsigned int B,unsigned int C>
FooStruct Get()
{
FooStruct temp = {A,B,C};
return temp;
}
}
}

namespace NSbase
{
namespace NStwo
{
class CFoo
{
public:
void foo( NSone::FooStruct defaultArg = NSone::Get<0,0,0>() );

};

void CFoo::foo( NSone::FooStruct defaultArg )
{
}
}
}

int main()
{
return 0;
}


Error is:
error C2783: 'NSbase::NSone::FooStruct NSbase::NSone::Get(void)' : could not deduce template argument for 'A'
...



Share on other sites
Visual Studio 2005 by the way. Because it's OK in gcc...

Share on other sites
Just wanted to make sure that it is in fact a compiler bug... sounds like it is so.

(Last bump, promise)

Share on other sites
I get errors on MinGW 4.2.1, too:

ns.cpp:26: error: expected identifier before numeric constantns.cpp:26: error: expected ',' or '...' before numeric constantns.cpp:26: error: parse error in template argument listns.cpp:26: error: default argument for parameter of type 'NSbase::NSone::FooStruct' has type '<unresolved overloaded function type>'ns.cpp:26: error: default argument missing for parameter 2 of 'void NSbase::NStwo::CFoo::foo(NSbase::NSone::FooStruct, int)'ns.cpp:30: error: prototype for 'void NSbase::NStwo::CFoo::foo(NSbase::NSone::FooStruct)' does not match any in class 'NSbase::NStwo::CFoo'ns.cpp:26: error: candidate is: void NSbase::NStwo::CFoo::foo(NSbase::NSone::FooStruct, int)ns.cpp:30: warning: unused parameter 'defaultArg'error: system call returned unexpected exit-code 1

EDIT: however, adding () around NSone::Get<0,0,0> shuts it up?!

Share on other sites
I believe this is a parse problem, similar to the nested template parameter parse (A<A<int>>). I'd have to dig through the standard to make sure, though. In other words, the compiler is seeing this:
void foo( FooStruct defaultArg = Get < 0, 0...

This explains the error messages; the compiler knows about Get, and thinks you're trying to compare it's addres to zero (nonsensical, of course, but the compiler's not that smart). VC++ points out that it can't determine which Get you want ("can't deduce template argument"). Did VS produce any more errors?

Either way, GCC seems to uncharacteristically produce the better diagnostic here. It tells you it expected some other identifier before what it saw as a dangling constant (the subsequent zero) - the next error message indicate it was looking for another parameter, or an ... token. A later message further suggests it has decided foo was a function taking an int, et cetera.

The parens (or wrapping the call to Get<0,0,0> in another function with no template parameters and calling that, or something) are the solution.

(FWIW, I tried it with GCC 3.4.6 and it fails. With or without namespaces.)

[Edited by - jpetrie on September 25, 2007 3:25:16 PM]

Share on other sites
Quote:
 Original post by jpetrieI believe this is a parse problem, similar to the nested template parameter parse (A>). I'd have to dig through the standard to make sure, though. In other words, the compiler is seeing this:void foo( FooStruct defaultArg = Get < 0, 0...

I should have mentioned that I tried lobbing in (heh, rigorous) the template keyword before "Get", but to no avail.

Share on other sites
Quote:
 Original post by jpetrieDid VS produce any more errors?

No. :(

Quote:
 Original post by jpetrieThe parens (or wrapping the call to Get<0,0,0> in another function with no template parameters and calling that, or something) are the solution.

That's actually what I ended up doing.

Share on other sites
Quote:
 I should have mentioned that I tried lobbing in (heh, rigorous) the template keyword before "Get", but to no avail.

Yeah, that wouldn't be legal syntax in that context. I'm fairly sure it's just a parse deficiency that was too hard to properly implement.

Share on other sites
I'll note that I was able to get the compiler to shut up and do the right thing by bringing NSone::Get into NStwo's namespace, either by
using NSone::Get;

or
using namespace NSone;

and then modifying the offending line to:
void foo( NSone::FooStruct defaultArg = Get<0,0,0>() );

but of course, that is defeating the purpose of having them in separate namespaces to begin with...