Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Unqualified lookup fails...

Reply
Thread Tools

Unqualified lookup fails...

 
 
Werner
Guest
Posts: n/a
 
      07-26-2012
Hi All,

The following code fails to compile on GCC 4.7.
I've now learned because of its compliance. I've
also noticing it failing under Comeau. On moving
the functions in the anonymous namespace above the
definition of Xx, it compiles:

------------------------------------------------
template <class T>
struct Xx
{
Xx()
{
T inst;
int n = sequenceSize( inst );
}
};


struct Header1
{
int sequenceSize_;
};

struct Header2
{
int itemCount_;
};

namespace {
int sequenceSize( const Header1& h )
{
return h.sequenceSize_;
}
int sequenceSize( const Header2& h )
{
return h.itemCount_;
}
}


void testUnqualifiedLookup()
{
Xx<Header1> xH1;
Xx<Header2> xH2;
}

Now (the question):

What would be the best way to fix this kind of problem?

A couple of options exist:

1) Functions sequenceSize would be found if they were
in the same namespaces as classes "Headerx" (by ADL).

2) A declaration of sequenceSize need at least exist
prior to the template definition.

I now have a case like this:

struct MsgX
{
int sequenceSizeOfA_;
int sequenceSizeOfB_;

std::vector<A> a_;
std::vector<B> b_;
};

I still would like the calling code (in the template
to work, therefore:

//Translation Unit A:
namespace {
int sequenceSize( const MsgX& msg )
{
return msg.sequenceSizeOfA_;
}
}
#include "Xx.h"

//Translation Unit B:
namespace {
int sequenceSize( const MsgX& msg )
{
return msg.sequenceSizeOfB_;
}
}
#include "Xx.h"

.... but this makes the compilation dependent on
the order of inclusion. Also, in this case
I cannot use ADL, because in both instances
of sequenceSz, the argument type is the same.

Now the question:

1) Is it bad of Xx to depend on an unqualified name?

2) If I'm not able to change Xx, what would be a good
solution - to include the declaration of sequenceSize
above Xx?

3) If I am allowed to change Xx, what would you do?

Kind regards,

Werner





 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      07-26-2012
On Jul 26, 1:22*pm, Werner wrote:

> ------------------------------------------------
> template <class T>
> struct Xx
> {
> * Xx()
> * {
> * * T inst;
> * * int n = sequenceSize( inst );
> * }
>
> };


[snip]

> A couple of options exist:
>
> 1) Functions sequenceSize would be found if they were
> in the same namespaces as classes "Headerx" (by ADL).


This sounds like the way to go.

> 2) A declaration of sequenceSize need at least exist
> prior to the template definition.


No, don't do that. Rely on ADL.

> I now have a case like this:
>
> struct MsgX
> {
> * int sequenceSizeOfA_;
> * int sequenceSizeOfB_;
> * std::vector<A> a_;
> * std::vector<B> b_;
> };
>
> I still would like the calling code (in the template
> to work, therefore:
>
> //Translation Unit A:
> namespace {
> * int sequenceSize( const MsgX& msg )
> * {
> * * return msg.sequenceSizeOfA_;
> * }}
>
> #include "Xx.h"
>
> //Translation Unit B:
> namespace {
> * int sequenceSize( const MsgX& msg )
> * {
> * * return msg.sequenceSizeOfB_;
> * }}
>
> #include "Xx.h"
>
> ... but this makes the compilation dependent on
> the order of inclusion.


Not only that. I believe it is also a violation of the ODR (one
definition rule) since you rely on two different versions of
Xx<MessageX>::Xx. So, this is not even an option unless you are fine
with unedfined behaviour.

> Also, in this case
> I cannot use ADL, because in both instances
> of sequenceSz, the argument type is the same.


You could use a wrapper type + ADL:

struct wrapper_MsgX_A
{
MsX data;
};

int sequenceSize(wrapper_MsgX_A const& x)
{ return x.data.sequenceSizeOfA_; }

...

Xx<wrapper_MsgX_A> foo;

> Now the question:
>
> 1) Is it bad of Xx to depend on an unqualified name?


No. It's good since it allows ADL and ADL is a good thing.

> 2) If I'm not able to change Xx, what would be a good
> solution - to include the declaration of sequenceSize
> above Xx?


No.

> 3) If I am allowed to change Xx, what would you do?


Keep it as it is or introduce another layer of indirection via a
traits
class or additional template parameter for Xx.


Cheers!
SG

 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      07-26-2012
On 7/26/2012 7:22 AM, Werner wrote:
> The following code fails to compile on GCC 4.7.
> I've now learned because of its compliance. I've
> also noticing it failing under Comeau. On moving
> the functions in the anonymous namespace above the
> definition of Xx, it compiles:
>
> ------------------------------------------------
> template <class T>
> struct Xx
> {
> Xx()
> {
> T inst;
> int n = sequenceSize( inst );
> }
> };
>
>
> struct Header1
> {
> int sequenceSize_;
> };
>
> struct Header2
> {
> int itemCount_;
> };
>
> namespace {
> int sequenceSize( const Header1& h )
> {
> return h.sequenceSize_;
> }
> int sequenceSize( const Header2& h )
> {
> return h.itemCount_;
> }
> }
>
>
> void testUnqualifiedLookup()
> {
> Xx<Header1> xH1;
> Xx<Header2> xH2;
> }


So, the function 'sequenceSize' used in the template has to have been
declared at the point of its first encounter by the compiler. Can you
declare it somehow without defining? See below for different examples.

> Now (the question):
>
> What would be the best way to fix this kind of problem?


"The best" depends on the definition of "good" and the criteria for
comparing two "good" solutions.

> A couple of options exist:
>
> 1) Functions sequenceSize would be found if they were
> in the same namespaces as classes "Headerx" (by ADL).


Which is a very good idea, BTW. Those need to be members, which would
make them class-specific or instance-specific, which is essentially what
they are now anyway. Of course that would make the classes or instances
"sequence-aware", IOW there will be some design dependency between the
class and the concept of "sequence" or "sequence size". Is that bad?

> 2) A declaration of sequenceSize need at least exist
> prior to the template definition.


Yes, that's the first thing that came to my mind.

> I now have a case like this:
>
> struct MsgX
> {
> int sequenceSizeOfA_;
> int sequenceSizeOfB_;
>
> std::vector<A> a_;
> std::vector<B> b_;
> };
>
> I still would like the calling code (in the template
> to work, therefore:
>
> //Translation Unit A:
> namespace {
> int sequenceSize( const MsgX& msg )
> {
> return msg.sequenceSizeOfA_;
> }
> }
> #include "Xx.h"
>
> //Translation Unit B:
> namespace {
> int sequenceSize( const MsgX& msg )
> {
> return msg.sequenceSizeOfB_;
> }
> }
> #include "Xx.h"
>
> ... but this makes the compilation dependent on
> the order of inclusion. Also, in this case
> I cannot use ADL, because in both instances
> of sequenceSz, the argument type is the same.
>
> Now the question:
>
> 1) Is it bad of Xx to depend on an unqualified name?


This is too general a question to be answered with certainty, so the
answer is "it depends". And there are too many factors to list, IMO.

> 2) If I'm not able to change Xx, what would be a good
> solution - to include the declaration of sequenceSize
> above Xx?


You can always wrap the header in which Xx comes in your own header and
include anything before and/or after that. Depending on your build
environment there are ways to hide the original header from being
included "by mistake".

> 3) If I am allowed to change Xx, what would you do?


I'd tell you to go for it <g>... On a serious note, I don't know.
Again, it depends. You need to look at the overall design of your
system and see whether it makes sense in your case to make 'Header1' and
'Header2' classes to have an inlined member function 'int
sequenceSize()' that would return the respective values.

Here is another solution, and if you can't change the header in which Xx
template resides, wrap it to add the declaration:

// -- inside the wrapper header
namespace {
template<class T> int sequenceSize(const T&);
}
// -- the wrapping header includes the Xx header:
template <class T>
struct Xx
{
int m_size;
Xx() : m_size(sequenceSize(T()))
{
}
};
// ---- end of the wrapper

struct Header1
{
int sequenceSize_;
};

struct Header2
{
int itemCount_;
};

namespace {
template<>
int sequenceSize<Header1>( const Header1& h )
{
return h.sequenceSize_;
}
template<>
int sequenceSize<Header2>( const Header2& h )
{
return h.itemCount_;
}
}

int main()
{
Xx<Header1> xH1;
Xx<Header2> xH2;
}

Keep in mind that if you don't need your 'sequenceSize' specializations
in the unnamed namespace, remove the declaration of the template from it
as well. That's what I'd do anyway.

V
--
I do not respond to top-posted replies, please don't ask
 
Reply With Quote
 
Werner
Guest
Posts: n/a
 
      07-26-2012
On Thursday, July 26, 2012 1:44:32 PM UTC+2, SG wrote:

> Not only that. I believe it is also a violation of the ODR (one
> definition rule) since you rely on two different versions of
> Xx&lt;MessageX&gt;::Xx. So, this is not even an option unless you are fine
> with unedfined behaviour.


Hmmm. I did not even think of that possibility. This would then
probably be why they decided to have that rule in the first place
(declaration visible at point of definition, as opposed to point
of instantiation). I've discovered this when moving to GCC 4.7.

> Keep it as it is or introduce another layer of indirection via a
> traits
> class or additional template parameter for Xx.


Yes, in fact Xx has an additional template parameter defining the
data, but is was not used in sequenceSize.

I've now resolved to this:

template <class HdrT, class DataT>
struct HdrSequenceMsgModel
{
HdrSequenceMsgModel()
{
HdrT inst;
std::size_t n = sequenceSize( inst, boost::mpl::identity<DataT>() );
}
};

and...

namespace SomeSpace{
class Header;
class Data;
std::size_t sequenceSize( const Header&, boost::mpl::identity<Data> );
};

Thank you,

Regards,

W
 
Reply With Quote
 
Werner
Guest
Posts: n/a
 
      07-26-2012
On Jul 26, 1:57*pm, Victor Bazarov <v.baza...@comcast.invalid> wrote:

[snip]

> Here is another solution, and if you can't change the header in which Xx
> template resides, wrap it to add the declaration:
>
> * * // -- inside the wrapper header
> * * namespace {
> * * * *template<class T> int sequenceSize(const T&);
> * * }
> * * // -- the wrapping header includes the Xx header:
> * * template <class T>
> * * struct Xx
> * * {
> * * * *int m_size;
> * * * *Xx() : m_size(sequenceSize(T()))
> * * * *{
> * * * *}
> * * };
> * * // ---- end of the wrapper
>
> * * struct Header1
> * * {
> * * * *int sequenceSize_;
> * * };
>
> * * struct Header2
> * * {
> * * * *int itemCount_;
> * * };
>
> * * namespace {
> * * * *template<>
> * * * *int sequenceSize<Header1>( const Header1& h )
> * * * *{
> * * * * * return h.sequenceSize_;
> * * * *}
> * * * *template<>
> * * * *int sequenceSize<Header2>( const Header2& h )
> * * * *{
> * * * * * return h.itemCount_;
> * * * *}
> * * }
>
> * * int main()
> * * {
> * * * *Xx<Header1> xH1;
> * * * *Xx<Header2> xH2;
> * * }
>
> Keep in mind that if you don't need your 'sequenceSize' specializations
> in the unnamed namespace, remove the declaration of the template from it
> as well. *That's what I'd do anyway.


Interesting idea. I haven't thought of using a wrapper header. It
would still not work for the last case documented, where one
has one type containing two lists:

struct MsgX
{
int sequenceSizeOfA_;
int sequenceSizeOfB_;

std::vector<A> a_;
std::vector<B> b_;
};

....but it is certainly a nice solution for similar problems
if one is not able to modify the template.

Thanks,

Regards, Werner
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Unqualified name lookup doubt (ISO/IEC-14882:2003 3.4.1/13) murali.desikan@gmail.com C++ 4 02-05-2008 10:08 PM
Unqualified element in XSD definition mavis XML 3 06-02-2006 05:30 AM
Unqualified element in XSD definition Mavis Java 1 06-02-2006 01:35 AM
SyntaxError: unqualified exec is not allowed in ... ? j vickroy Python 1 10-08-2003 05:10 PM
qualified and unqualified local elements (was: My schema validation is not working?) C. M. Sperberg-McQueen XML 0 07-31-2003 01:59 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57