|
Boost : |
From: Hamish Mackenzie (boost_at_[hidden])
Date: 2002-02-18 03:05:33
I know it is a language extension, so not what you wanted, but my
preference is for constants to be converted to types by the compiler.
They would become something like
template< typename Type, Type Value >
struct constant
{
static Type value = Value;
constant();
operator const Type & () const { return value; }
};
For instance
f( 5 );
would be the same as
f( constant< int, 5 >() );
I don't think the conversion should always be allowed for instance
5 x;
should probable not be converted to
constant< int, 5 > x;
It would allow things like
template< typename Port = 80 >
class http_connection_arguments
{
Port port_;
public:
explicit http_connection_arguments( Port p = Port() ):port_( p ) {}
...
};
Then if I need to write a program that connects to another port I can
simple write
http_connection_arguments< 8080 > args;
If the port isn't known until run time then I can use
http_connection_arguments< int > args( runtime_port );
This would be a type mismatch error...
http_connection_arguments<> args( 5 );
But this would work...
http_connection_arguments<> args( 80 );
String constants would be based on type lists of constant< char, ??? >.
Something like...
template< typename CharType, typename CharactersTypeList >
struct constant_string
{
typedef CharType char_type;
constant_string();
operator char_type * ()
{ return construct_string<CharactersTypeList>(); }
};
construct_string can be hacked together using a nested class something
like...
template< typename TypeList >
struct constant_string_data;
template<>
struct constant_string_data< TYPELIST_0 > {};
template< typename CharType, CharType Char, typename Tail >
struct constant_string_data<
typelist< constant< Char_Type, Char >, Tail > >
{
CharType buffer_[1];
constant_string_data< Tail > tail_;
};
template< typename CharType, CharType Char, typename Tail >
CharType constant_string_data::buffer_[1] = { Char };
Mix that with a singleton template and it should work but it depends on
the compiler using byte allignment, it doesn't merge strings and it
probably produces loads of code to initialize each character. I am sure
the compiler could do a better job.
So your example of strncpy could be...
template< typename CharType,
int BufferSize,
typename SourceTypeList,
int Count >
void strncpy( some_kind_of_vector_type< CharType, BufferSize > &buf,
constant_string< CharType, CharactersTypeList > s,
constant< int, Count > c
{
BOOST_STATIC_ASSERT( BufferSize > Count );
BOOST_STATIC_ASSERT( Count > size< CharactersTypeList >::value );
std::strncpy( buf.raw_buffer(), s, c );
}
some_kind_of_vector_type< char, 256 > buf;
strncpy( buffer, "something", 512 );
Unfortunately all this would break lots of existing code such as
template< typename T >
void f( T ) {}
void f( int ) {}
f( 5 ); // oops no longer calls f( int )
A fix for this would be to only let template arguments be
constant< X, Y > if it is explicitly allowed
template< allow_constants typename T >
void f( T ) {}
or perhaps only allow the conversion when it is explicitly requested
strncpy( b, typename "something"(), typename 512() );
I would be happy with an extension which just treated constant_string
specially...
strncpy( b, constant_string< "something" >(), int_c< 512 >() );
where int_c is a template typedef of constant< int, Value >
Hamish
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk