GCC 3.4 being picky

  • Thread starter Asfand Yar Qazi
  • Start date
A

Asfand Yar Qazi

Hi,

I'm testing the gcc-3.4 branch (built with 'make profilebootstrap' sped
up compiles by a massive 10%!)

Its got better conformance to the C++ Standard (hence this is not an OT
post.) I'm having trouble figuring out what it wants me to do. Here's
some code, and the error messages generated.

namespace NA
{


namespace N1
{

template<typename SomeT>
class Tmp1
{
};

template<typename T1, typename T2 = Tmp1<T1> >
class C1
{
public:
template<unsigned i>
class C2
{
};
};



};

};

namespace NA
{

namespace N2
{

template<typename B>
B
a_func(const N1::C1<B>::template C2<3>& arg)
{
}

};

};

int
main()
{
using namespace NA;
using namespace N1;
N1::C1<double>::C2<3> v;

N2::a_func<double>(v);

return 0;
}

one.cc:40: error: expected unqualified-id before '&' token
one.cc:40: error: expected `,' or `...' before '&' token
one.cc:41: error: ISO C++ forbids declaration of `parameter' with no type
one.cc: In function `int main()':
one.cc:55: error: cannot convert `NA::N1::C1<double,
NA::N1::Tmp1<double> >::C2<3u>' to `int' for argument `1' to `B
NA::N2::a_func(int) [with B = double]'

I know its some problem with the 'a_func ....' line.

Before it read:
a_func(const N1::C1<B>::C2<3>& arg)

and gave the error message:
one.cc:40: error: non-template `C2' used as template
one.cc:40: error: (use `NA::N1::C1<B, NA::N1::Tmp1<T1> >::template C2'
to indicate that it is a template)
one.cc:40: error: expected unqualified-id before ')' token


Ideas? I'm finally getting my SSE-optimised templated expression using
vector-maths library off the ground now that GCC isn't full of
template-parsing bugs, but it seems that I can't figure out the correct
behaviour anyway :)

Thanks,
Asfand Yar
 
B

Buster

Asfand said:
namespace NA
{

namespace N2
{

template<typename B>
B
a_func(const N1::C1<B>::template C2<3>& arg)
{
}
[...]

I know its some problem with the 'a_func ....' line.

Before it read:
a_func(const N1::C1<B>::C2<3>& arg)

I don't know how much of this is redundant, but it's legal:

a_func (const typename N1::template C1 <B>::template C2 <3> & arg)
 
B

Buster

template <typename B>
B
a_func (const typename N1::template C1 <B>::template C2 <3> & arg)
{
}

Perhaps an explanation is in order. In the parameter list,

"N1" is fine. It is not dependent on a template argument and has already
been defined. It is definitely the name of a namespace.

"N1::C1" is also OK: it is definitely the name of a template.

"N1::C1 <B>" is therefore OK too.

"N1::C1 <B>::C2" might not be the name of a template (*)! It depends
on B.

The compiler is supposed to assume it is _not_ a template. Therefore
the '<' following this name is interpreted as the less-than operator.
Syntax error. We have to say "N1::C1 <B>::template C2" instead.

"N1::C1 <B>::template C2 <3>" might not be the name of a type (**)! It
depends on B and 3. The compiler is supposed to assume it is _not_ the
name of a type. Therefore the '&' following this name is interpreted
as the bitwise-and operator. Syntax error. We have to say
"typename N1::C1 <B>::template C2 <3>" instead.

So the final parameter declaration becomes
"const typename N1::C1 <B>::template C2 <3> & arg".

The extra "template" I put in in my previous post doesn't do any harm
but it is redundant.

(*) // We can _make_ C2 not be a template, using partial specialization:
namespace N1 { template <> class C1 <int> { int C2; }; }
// ...
void f () { N1::C1 <int>::C2 <3> & arg; } // Ouch.

(**) // Similarly.
 
A

Asfand Yar Qazi

Buster wrote:
So the final parameter declaration becomes
"const typename N1::C1 <B>::template C2 <3> & arg".

So is this a GCC bug?

namespace NA {
namespace N1 {

template<typename SomeT>
class Tmp1
{
};

template<typename T1, typename T2 = Tmp1<T1> >
class C1
{
public:
template<unsigned i>
class C2
{
};
};

} // namespace N1
} // namespace NA

namespace NA {
namespace N2 {

template<typename B>
B a_func(const N1::template C1<B>::template C2<3>& arg)
{
}

} // namespace N2
} // namespace NA

int
main()
{
NA::N1::C1<double>::C2<3> v;
NA::N2::a_func<double>(v);
return 0;
}

one.cc:26: error: expected unqualified-id before '&' token
one.cc:26: error: expected `,' or `...' before '&' token
one.cc:27: error: ISO C++ forbids declaration of `parameter' with no type
one.cc: In function `int main()':
one.cc:37: error: cannot convert `NA::N1::C1<double,
NA::N1::Tmp1<double> >::C2<3u>' to `int' for argument `1' to `B
NA::N2::a_func(int) [with B = double]'
 
B

Buster

Asfand said:
Buster wrote:
So the final parameter declaration becomes
"const typename N1::C1 <B>::template C2 <3> & arg".

So is this a GCC bug?
[...]

template<typename B>
B a_func(const N1::template C1<B>::template C2<3>& arg)
{
}

You forgot the 'typename'.
 
R

Rob Williscroft

Asfand Yar Qazi wrote in
Buster wrote:


So is this a GCC bug?

No the code is AFAICT illegal, gcc produces a diagnostic and fails
to compile, what more could you ask for.

[snip]
namespace NA {
namespace N2 {

template<typename B>
B a_func(const N1::template C1<B>::template C2<3>& arg)

This should be (as buster has already said):

B a_func( typename N1::C1<B>::template C2<3> const & /*arg*/ )

typename is needed as C2< 3 > is a type, the first template is
IIUC illegal as N1 is namespace not a class, template used this way
at namespace scope is used to explicitly instabtiate a template and
has no place in an paramiter list.


Rob.
 
A

Asfand Yar Qazi

Buster said:
Asfand said:
Buster wrote:
So the final parameter declaration becomes
"const typename N1::C1 <B>::template C2 <3> & arg".

So is this a GCC bug?

[...]

template<typename B>
B a_func(const N1::template C1<B>::template C2<3>& arg)
{
}


You forgot the 'typename'.

whoops. Cool it works! many thanks.
 
A

Asfand Yar Qazi

Rob said:
Asfand Yar Qazi wrote in
Buster wrote:


So is this a GCC bug?


No the code is AFAICT illegal, gcc produces a diagnostic and fails
to compile, what more could you ask for.

[snip]

namespace NA {
namespace N2 {

template<typename B>
B a_func(const N1::template C1<B>::template C2<3>& arg)


This should be (as buster has already said):

B a_func( typename N1::C1<B>::template C2<3> const & /*arg*/ )

typename is needed as C2< 3 > is a type, the first template is
IIUC illegal as N1 is namespace not a class, template used this way
at namespace scope is used to explicitly instabtiate a template and
has no place in an paramiter list.


Rob.

Thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top