Thread overview
boost tuples
Feb 09, 2003
Richard Grant
Feb 10, 2003
Richard Grant
Feb 10, 2003
Walter
Feb 10, 2003
Richard Grant
Feb 21, 2003
Richard Grant
Feb 21, 2003
Walter
February 09, 2003
Christof,

Have you used boost::tuples with the recent beta, and if so are there any problems of note?

I have had some good success using them, but I'm chasing a generic compiler error, and I wonder if perhaps something is wrong in the tuple precompiler maze.

Richard


February 10, 2003
Tuples uses recursive template member function template, and the inline keyword seems to be causing some troubles.. The following compiles and executes if the inline keyword is removed.

#include <iostream>

template <int N>
struct A {
template <class T1>
inline static T1 get(T1& t) {
// Error:  storage class is illegal in this context
std::cout << "Recurse: " << N << std::endl;
return A<N-1>:: get<T1>(t);
// Error: no instance of class 'A<0>' for member 'A<0>::get'
}
};

template<>
struct A<0> {
template <class T1>
inline static T1 get(T1& t) {
// Error:  storage class is illegal in this context
std::cout << "Recurse: Final" << std::endl;
return t;
}
};

struct B { };

void main() {
B b;
A<3>::get<B>(b);
// Error: no instance of class 'A<3>' for member 'A<3>::get'
}

Richard


February 10, 2003
Got it!


February 10, 2003
In the example below, the output matches the correct base class representation. However, the conversion from derived class to base class fails. You can change the last line like get_class<1> for another set of errors like:

Warning 11: non-const reference initialized to temporary
Error: need explicit cast for function parameter 1 to get
from: cons<int ,null_type >
to  : cons<int ,null_type >

Sorry the example is long, but getting the inheritence list from the implementation was a pain. There is probably something else lurking, but I'm hoping that this is a good start.

Richard

struct null_type {};

inline const null_type cnull() { return null_type(); }

template <class T0 = null_type, class T1 = null_type,
class T2 = null_type> class tuple;

template <class HT, class TT>
struct cons {

typedef HT head_type;
typedef TT tail_type;

head_type head;
tail_type tail;

template <class T1, class T2, class T3>
cons( T1& t1, T2& t2, T3& t3 )
: head (t1),
tail (t2, t3, cnull())
{ }

template <class T2, class T3>
cons( const null_type& t1, T2& t2, T3& t3 )
: head (),
tail (t2, t3, cnull())
{}

};

template <class HT>
struct cons<HT, null_type> {

typedef HT head_type;
typedef null_type tail_type;
typedef cons<HT, null_type> self_type;

head_type head;

template<class T1>
cons(T1& t1, const null_type&, const null_type&)
: head (t1) {}

cons(const null_type&, const null_type&, const null_type&)
: head () {}
};

template <class T0, class T1, class T2>
struct mapper
{
typedef cons<T0,
typename mapper<T1, T2, null_type>::type
> type;
};

template <>
struct mapper<null_type, null_type, null_type>
{
typedef null_type type;
};

template <class T0, class T1, class T2>
class tuple :
public mapper<T0, T1, T2>::type
{
public:
typedef typename
mapper<T0, T1, T2>::type inherited;
typedef typename inherited::head_type head_type;
typedef typename inherited::tail_type tail_type;

tuple()
: inherited(cnull(), cnull(), cnull()) {}

tuple(const T0& t0)
: inherited(t0, cnull(), cnull()) {}

tuple(const T0& t0,
const T1& t1)
: inherited(t0, t1, cnull()) {}

tuple(const T0& t0,
const T1& t1,
const T2& t2)
: inherited(t0, t1, t3) {}
};

template <>
class tuple<null_type, null_type, null_type> :
public null_type
{
public:
typedef null_type inherited;
};

template< int N >
struct get_class {
template<class RET, class HT, class TT >
static RET get(cons<HT, TT>& t)
{
return get_class<N-1>:: get<RET>(t.tail);
}
};

template<>
struct get_class<0> {
template<class RET, class HT, class TT>
static RET get(cons<HT, TT>& t)
{
return t.head;
}
};

void main() {

tuple<int,int> test(10, 12);

int a = get_class<0>::get<int>(test);
// Warning 11: non-const reference initialized to temporary
// Error: need explicit cast for function parameter 1 to get
// from: tuple<int ,int ,null_type >
// to  : cons<int ,cons<int ,null_type > >

}


February 21, 2003
In article <b29e98$1b8$1@digitaldaemon.com>, Richard Grant says...
>
>
>In the example below, the output matches the correct base class

ok, that entire example was wrong. After spending some time with it and the tuple sources, I have found that the problem is in the public interface and not the representation. The good news is that I can report that the entire underlying representation works with current beta. The bad news is that according to standard (see 14.8.1 for an example - not a justification), explicit argument specification and argument deduction are in need of adjustment. Here's the test case:

template <class T1> struct A { };

template<int N, class HT>
int get(A<HT>& c) {
int i = N;
return i;
}

int main() {
A<int> a;
int j = get<1>(a);
// Error: illegal operand types
// Had: int
// and: A<int >
}

Richard


February 21, 2003
Great!