|
Boost : |
From: Howard Hinnant (hinnant_at_[hidden])
Date: 2000-06-10 10:26:46
I can repeat the thought process that I went through:
I started with the following templated class:
template <typename T>
class A
{
public:
A(param_type data);
value_type return_by_value() const;
reference return_by_reference();
const_reference return_by_const_reference() const;
private:
T data_;
};
I wanted to use call_traits so that no matter what T was, I could:
1. Pass T into the class (param_type)
2. Pass T out of the class by value (value_type)
3. Pass T out of the class by reference (reference)
4. Pass T out of the class by const reference (const_reference)
I set up a test-bed to do this and experimented with pods, references and
arrays. The following test-bed is not a pass-fail sort of thing. You
have to study the code to decide what is "right".
template <typename T>
class A
{
public:
typedef typename call_traits<T>::value_type value_type;
typedef typename call_traits<T>::reference reference;
typedef typename call_traits<T>::const_reference const_reference;
typedef typename call_traits<T>::param_type param_type;
A(param_type data) : data_(data) {}
value_type return_by_value() const {return data_;}
reference return_by_reference() {return data_;}
const_reference return_by_const_reference() const {return data_;}
private:
T data_;
};
template <typename T, std::size_t sz>
class A<T[sz]>
{
public:
typedef typename call_traits<T[sz]>::value_type value_type;
typedef typename call_traits<T[sz]>::reference reference;
typedef typename call_traits<T[sz]>::const_reference const_reference;
typedef typename call_traits<T[sz]>::param_type param_type;
A(param_type data) {std::memcpy(data_, data, sz*sizeof(T));}
value_type return_by_value() const {return data_;}
reference return_by_reference() {return data_;}
const_reference return_by_const_reference() const {return data_;}
private:
T data_[sz];
};
int main()
{
{
int i = 1;
std::cout << "i = " << i << '\n';
A<int> a1(1);
int& i1 = a1.return_by_reference();
i1 = 2;
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
const int& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
int i3 = a1.return_by_value();
std::cout << "i3 = " << i3 << '\n';
}
std::cout << '\n';
{
int i = 1;
std::cout << "i = " << i << '\n';
A<int&> a1(i);
int& i1 = a1.return_by_reference();
i1 = 2;
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
const int& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
int i3 = a1.return_by_value();
std::cout << "i3 = " << i3 << '\n';
}
std::cout << '\n';
{
int* i = reinterpret_cast<int*>(0x01);
std::cout << "i = " << i << '\n';
A<int*> a1(i);
int*& i1 = a1.return_by_reference();
i1 = reinterpret_cast<int*>(0x02);
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
int*const& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
int* i3 = a1.return_by_value();
std::cout << "i3 = " << i3 << '\n';
}
std::cout << '\n';
{
int* i = reinterpret_cast<int*>(0x01);
std::cout << "i = " << i << '\n';
A<int*&> a1(i);
int*& i1 = a1.return_by_reference();
i1 = reinterpret_cast<int*>(0x02);
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
int*const& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
int* i3 = a1.return_by_value();
std::cout << "i3 = " << i3 << '\n';
}
std::cout << '\n';
{
typedef char Char4[4];
Char4 i = "abc";
std::cout << "i = " << i << '\n';
A<Char4> a1(i);
Char4& i1 = a1.return_by_reference();
std::strcpy(i1, "def");
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
const Char4& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
Char4 i3;
std::strcpy(i3, a1.return_by_value());
std::cout << "i3 = " << i3 << '\n';
}
std::cout << '\n';
{
typedef char Char4[4];
Char4 i = "abc";
std::cout << "i = " << i << '\n';
A<Char4&> a1(i);
Char4& i1 = a1.return_by_reference();
std::strcpy(i1, "def");
std::cout << "i = " << i << '\n';
std::cout << "i1 = " << i1 << '\n';
const Char4& i2 = a1.return_by_const_reference();
std::cout << "i2 = " << i2 << '\n';
}
}
The output I'm expecting is:
i = 1
i = 1
i1 = 2
i2 = 2
i3 = 2
i = 1
i = 2
i1 = 2
i2 = 2
i3 = 2
i = 0x00000001
i = 0x00000001
i1 = 0x00000002
i2 = 0x00000002
i3 = 0x00000002
i = 0x00000001
i = 0x00000002
i1 = 0x00000002
i2 = 0x00000002
i3 = 0x00000002
i = abc
i = abc
i1 = def
i2 = def
i3 = def
i = abc
i = def
i1 = def
i2 = def
I had to make a specialization of A<T> for arrays because of A's
constructor. But otherwise it is meant to be the same as the primary
template. Fixing up call_traits for arrays to make this work is what led
me to the design I posted. Perhaps my assumptions on the use of
call_traits are not what other's intended.
It might be a good idea to come up with more examples of how one would
expect to make use of call_traits with array types.
-Howard
John Maddock wrote on 6/10/2000 7:41 AM
>Dave,
>
>>Can someone explain the existence of the following in call_traits.hpp, and
>>how such code came to be accepted into a release library?
>
>Good question, doesn't look good does it? Looks like we forgot to finish
>this - in fact looking closer it's not clear how the array specialisation
>should look (and most current compilers don't actually need the array
>specialisation anyway), the most recent version (of several) was suggested
>by Howard, but doesn't meet the constructability guarantees. Here are the
>options:
>
>Option 1: doesn't meet constructability guarentees, but ensures that
>value_type is assignable:
>
>template <typename T, std::size_t N>
>struct call_traits<T [N]>
>{
> typedef T* const value_type; // hh was typedef T
>value_type[N];
> typedef T (&reference)[N]; // hh was typedef T*& reference;
> typedef const T (&const_reference)[N]; // hh was typedef const T*&
>const_reference;
> typedef value_type param_type; // hh was typedef T* param_type;
>};
>
>Option 2: meets constructability guarentees but value_type is not
>assignable:
>
>template <typename T, std::size_t N>
>struct call_traits<T [N]>
>{
>private:
> typedef T array_type[N];
>public:
> typedef array_type& value_type;
> typedef value_type reference;
> typedef const array_type& const_reference;
> typedef value_type param_type;
>};
>
>Thoughts?
>
>- John.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk