Boost logo

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;
    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_;
    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;
    operator char_type * ()
      { return construct_string<CharactersTypeList>(); }

construct_string can be hacked together using a nested class something
  template< typename TypeList >
  struct constant_string_data;

  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
  strncpy( b, constant_string< "something" >(), int_c< 512 >() );
where int_c is a template typedef of constant< int, Value >


Boost list run by bdawes at, gregod at, cpdaniel at, john at