Reputation: 7853
I have a Visual Studio 2013 C++11 project where I've defined a tree-like structure (where each element of an iterator is itself a container).
struct some_tree;
class some_tree_iterator
: public boost::iterator_facade<
some_tree_iterator,
some_tree,
std::forward_iterator_tag,
some_tree>
{
public:
// ...
private:
// error C2027: use of undefined type 'some_tree'
some_tree dereference() const { return some_tree( /*init values*/ ); };
// ...
};
struct some_tree
{
some_tree_iterator begin();
some_tree_iterator end();
std::string value() const;
};
int main(int argc, char* argv[])
{
some_tree foo;
for (auto x : foo)
{
std::cout << x.name() << std::endl;
for (auto y : x)
{
std::cout << "\t" << y.value() << std::endl;
}
}
return 0;
}
Is the only way around this use of undefined type
problem to return a pointer to a new some_tree
container? like this:
std::shared_ptr<some_tree> some_tree_iterator::dereference() const
{
return std::make_shared<some_tree>( /* init values*/ );
};
Upvotes: 0
Views: 406
Reputation: 1651
Two methods:
You must not reference the class until it is defined. So you must do:
struct some_tree;
class some_tree_iterator
{
public:
// ...
private:
some_tree dereference() const;
// ...
};
struct some_tree
{
some_tree_iterator begin();
some_tree_iterator end();
std::string value() const;
};
some_tree some_tree_iterator::dereference() const { return some_tree( /*init values*/ ); };
Also, you may do like STL and define the iterator inside the struct some_tree
(in fact, STL's iterators are templates so they are defined in the class, even if declared elsewhere):
struct some_tree
{
class iterator
: public boost::iterator_facade<
iterator,
some_tree,
std::forward_iterator_tag,
some_tree>
{
public:
private:
some_tree dereference() const { return some_tree( /*init values*/ ); };
};
iterator begin();
iterator end();
std::string value() const;
};
Upvotes: 1
Reputation: 96236
In cases when you need several classes that use each other as complete type, you can use something like this:
class TestClass1;
class TestClass2;
class TestClass1
{
int val;
TestClass2 foo();
};
class TestClass2
{
int val;
TestClass1 foo();
};
TestClass2 TestClass1::foo()
{
/* ... */
}
TestClass1 TestClass2::foo()
{
/* ... */
}
Upvotes: 0