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;
    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