Re: Unqualified lookup fails...
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