Very strange problem with namespace
From: Agoston Bejo (gusz1_at_freemail.hu)
Date: 06/12/04
- Previous message: GuitarBill: "Re: Inheriting from base class..."
- Messages sorted by: [ date ] [ thread ]
Date: Sat, 12 Jun 2004 22:01:52 +0200
Hello,
today is the day of questions for me. :) (That's because I have time mainly
on the weekends for this.)
I have tried to create an example code based on the program where the
problem occured, but as you can see, it got quite lengthy anyway. I'm very
sorry for that, but this is the shortest I could make that is concentrated
as tightly as possible around the problem.
If you take your time and read through the source code, you will notice that
I marked the critical parts with (*).
Briefly about the problem: In the code an item_proxy object is used that can
implicitly be converted to the corresponding value type and used as a
reference that is returned by an iterator. No matter what, the compiler
won't found the global operator< that takes value type as parameters when
you apply it to the item_proxy objects. If the ContainerFront class (that
contains item_proxy as an inner class) is not defined in namespace N, there
is no problem. Moreso, operator<< is found without problem in either case.
I just can't get any sense out of this.
Thx for your help,
Gus
---------------------------------------------------
Huge example code (once more, sorry) :
---------------------------------------------------
// xOpLessSucks.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
using namespace std;
using namespace boost;
// example class that is going to be used as a value type:
struct C {
int i;
C(int i):i(i) {}
C() {}
};
bool operator<(const C& lhs, const C& rhs) { // (*)
return lhs.i < rhs.i;
}
ostream& operator<<(ostream& out, const C& c) {
out << "c" << c.i;
return out;
}
// notice that ostream_iterator<C> is able to use this op<<,
// so the copy(...) lines all compile in _tmain().
namespace N { // (*)
// without putting ContainerFront into namespace N
// the code will compile.
template<typename T> struct ContainerFront
{
typedef vector<T> Container;
Container& m_rContainer;
ContainerFront(Container& container):m_rContainer(container) {}
T get(int i) const { return m_rContainer[i]; }
void set(int i, const T& value) const { m_rContainer[i] = value; }
struct item_proxy
{
public:
// the reason for this value placeholder / reference thing
// is not important now... but there is one. :)
item_proxy() {} // value placeholder
explicit item_proxy(const T& value):
m_isReference(false), m_value(value) {}
// value placeholder
item_proxy(ContainerFront* pContainerFront, int index):
m_isReference(true), m_pContainerFront(pContainerFront),
m_index(index)
{}
// reference
item_proxy(const item_proxy &rhs):
m_isReference(false),
m_value(static_cast<T>(rhs))
{}
// value placeholder
operator T() const { // (*)
return m_isReference ?
m_pContainerFront->get(m_index) : m_value;
}//operator T() const
item_proxy& operator=(const T &value) {
m_isReference ?
m_pContainerFront->set(m_index, value)
:
m_value = value;
return *this;
}
item_proxy& operator=(const item_proxy &rhs) {
return (*this = static_cast<T>(rhs));
}
protected:
bool m_isReference;
ContainerFront *m_pContainerFront;
int m_index;
T m_value;
};//struct item_proxy
class iterator :
public iterator_facade< iterator, T,
std::random_access_iterator_tag, item_proxy >
// never mind if you don't know iterator_facade.
// the main point is that it uses the methods defined in the
// private section to define a standard iterator interface
// for this class.
{
public:
iterator(ContainerFront* pContainerFront, int i):
m_pContainerFront(pContainerFront), m_index(i) {}
iterator():m_pContainerFront(0) {}
private:
friend class iterator_core_access;
void increment() { ++m_index; }
void decrement() { --m_index; }
void advance(difference_type n) { m_index += (int)n; }
difference_type distance_to(const iterator &rhs) const
{
return rhs.m_index - m_index;
}
bool equal(const iterator &rhs) const {
return m_index == rhs.m_index;
}
reference dereference() const {
// reference: typedef for item_proxy
return item_proxy(m_pContainerFront, m_index);
}
ContainerFront* m_pContainerFront;
int m_index;
};//class iterator
iterator begin() { return iterator(this, 0); }
iterator end() {
return iterator(this, (int)m_rContainer.size());
}
};//template<typename T> struct ContainerFront
}//namespace N
using namespace N;
namespace M {
template<typename TIterator>
void f(TIterator it1, TIterator it2) {
while (it1 < it2
&& !(*(it2 - 1) < *it2)
&& !(*it2 < *(it2 - 1)))
--it2;
// The compiler reports error for a line exactly equivalent to this
// while compiling std::sort
// This here compiles, however.
// This function itself makes no sense, I just copied out the
// line on which the compiler stumbles.
}
}//namespace M
using namespace M;
int _tmain(int argc, _TCHAR* argv[])
{
// test C:
C ic[] = {10,9,8,7,6,5,4,3,2,1};
vector<C> v(ic, ic+10);
copy(v.begin(), v.end(), ostream_iterator<C>(cout, " "));
cout << endl;
sort(v.begin(), v.end());
copy(v.begin(), v.end(), ostream_iterator<C>(cout, " "));
cout << endl;
// test ContainerFront:
cout << endl;
vector<C> vec(v.rbegin(), v.rend());
ContainerFront<C> cf(vec);
copy(v.rbegin(), v.rend(), cf.begin());
copy(cf.begin(), cf.end(), ostream_iterator<C>(cout, " "));
// (*) - here operator<< is used with no problem
cout << endl;
f(cf.begin(), cf.end());
sort(cf.begin(), cf.end()); // compile error (*)
// cannot find operator<
copy(cf.begin(), cf.end(), ostream_iterator<C>(cout, " "));
cout << endl;
return 0;
}
// Thank you for reading through the whole thing. You must be very patient!
- Previous message: GuitarBill: "Re: Inheriting from base class..."
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|