O
Oliver Kowalke
Hi,
i need a string which can be used with the stl and should have a fixed max.
length. strings with different max_lenght should be different types.
assignment/copy construction from a string with equal or less max_lenght
should be possible and vice versa not.
is my suggestion a good solution? any improvements? or does a better
solution exist?
thx,
Oliver
#include <iosfwd>
#include <string>
#include <stdexcept>
struct null_type;
template< bool B , typename T , typename E >
struct if_then_else;
template< typename T , typename E >
struct if_then_else< true , T , E>
{
typedef T result_type;
};
template< typename T , typename E >
struct if_then_else< false , T , E>
{
typedef E result_type;
};
template< int N >
class max_lenght_string
{
private:
std::string str_;
template< int M >
friend class max_lenght_string;
template< typename charT , typename traitsT >
friend std::basic_ostream< charT , traitsT >&
operator<<( std::basic_ostream< charT , traitsT >& os, max_lenght_string<
N > const& str);
template< int M >
static
std::string const&
access( typename if_then_else< N <= M , max_lenght_string< N > ,
null_type >::result_type const& str)
{
return str.str_;
}
static
std::string const&
check( std::string const& str)
{
if( str.size() > N)
throw std::runtime_error("string ist too large");
return str;
}
public:
max_lenght_string( std::string const& str)
:
str_( max_lenght_string::check( str) )
{}
max_lenght_string( char const* c)
:
str_( max_lenght_string::check( std::string( c) ) )
{}
max_lenght_string( max_lenght_string const& str)
:
str_( str.str_ )
{}
template< int M >
max_lenght_string( max_lenght_string< M > const& str)
:
str_( max_lenght_string< M >::access< N >( str) )
{}
max_lenght_string const&
operator=( max_lenght_string const& rhs)
{
max_lenght_string tmp( rhs);
str_.swap( tmp.str_);
return *this;
}
template< int M >
max_lenght_string const&
operator=( max_lenght_string< M > const& rhs)
{
max_lenght_string< N > tmp( rhs);
str_.swap( tmp.str_);
return *this;
}
// c_str(), iterators, begin(), end(), ... left open
};
template< typename charT , typename traitsT , int N >
if( ! os) return os;
os << str.str_;
return os;
}
int main(int argc, char *argv[])
{
try
{
max_lenght_string< 1 > a1("a");
max_lenght_string< 1 > a2("b");
max_lenght_string< 2 > a3("ab");
max_lenght_string< 2 > a4( a2); // ok
max_lenght_string< 2 > a5( a4); // ok
// max_lenght_string< 1 > a6( a3); // compile-time error
// max_lenght_string< 1 > a7("abc"); // run-time error
a1 = a2; // ok
a3 = a1; // ok
// a2 = a3; // compile-time error
std::cout << "a1 = " << a1 << std::endl;
std::cout << "a2 = " << a2 << std::endl;
std::cout << "a3 = " << a3 << std::endl;
std::cout << "a4 = " << a4 << std::endl;
std::cout << "a5 = " << a5 << std::endl;
return 0;
}
catch( std::exception const& ex)
{
std::cout << "exception : " << ex.what() << std::endl;
return 1;
}
catch(...)
{
std::cout << "unhandled exception" << std::endl;
return 1;
}
}
i need a string which can be used with the stl and should have a fixed max.
length. strings with different max_lenght should be different types.
assignment/copy construction from a string with equal or less max_lenght
should be possible and vice versa not.
is my suggestion a good solution? any improvements? or does a better
solution exist?
thx,
Oliver
#include <iosfwd>
#include <string>
#include <stdexcept>
struct null_type;
template< bool B , typename T , typename E >
struct if_then_else;
template< typename T , typename E >
struct if_then_else< true , T , E>
{
typedef T result_type;
};
template< typename T , typename E >
struct if_then_else< false , T , E>
{
typedef E result_type;
};
template< int N >
class max_lenght_string
{
private:
std::string str_;
template< int M >
friend class max_lenght_string;
template< typename charT , typename traitsT >
friend std::basic_ostream< charT , traitsT >&
operator<<( std::basic_ostream< charT , traitsT >& os, max_lenght_string<
N > const& str);
template< int M >
static
std::string const&
access( typename if_then_else< N <= M , max_lenght_string< N > ,
null_type >::result_type const& str)
{
return str.str_;
}
static
std::string const&
check( std::string const& str)
{
if( str.size() > N)
throw std::runtime_error("string ist too large");
return str;
}
public:
max_lenght_string( std::string const& str)
:
str_( max_lenght_string::check( str) )
{}
max_lenght_string( char const* c)
:
str_( max_lenght_string::check( std::string( c) ) )
{}
max_lenght_string( max_lenght_string const& str)
:
str_( str.str_ )
{}
template< int M >
max_lenght_string( max_lenght_string< M > const& str)
:
str_( max_lenght_string< M >::access< N >( str) )
{}
max_lenght_string const&
operator=( max_lenght_string const& rhs)
{
max_lenght_string tmp( rhs);
str_.swap( tmp.str_);
return *this;
}
template< int M >
max_lenght_string const&
operator=( max_lenght_string< M > const& rhs)
{
max_lenght_string< N > tmp( rhs);
str_.swap( tmp.str_);
return *this;
}
// c_str(), iterators, begin(), end(), ... left open
};
template< typename charT , typename traitsT , int N >
{std::basic_ostream said:const& str)
if( ! os) return os;
os << str.str_;
return os;
}
int main(int argc, char *argv[])
{
try
{
max_lenght_string< 1 > a1("a");
max_lenght_string< 1 > a2("b");
max_lenght_string< 2 > a3("ab");
max_lenght_string< 2 > a4( a2); // ok
max_lenght_string< 2 > a5( a4); // ok
// max_lenght_string< 1 > a6( a3); // compile-time error
// max_lenght_string< 1 > a7("abc"); // run-time error
a1 = a2; // ok
a3 = a1; // ok
// a2 = a3; // compile-time error
std::cout << "a1 = " << a1 << std::endl;
std::cout << "a2 = " << a2 << std::endl;
std::cout << "a3 = " << a3 << std::endl;
std::cout << "a4 = " << a4 << std::endl;
std::cout << "a5 = " << a5 << std::endl;
return 0;
}
catch( std::exception const& ex)
{
std::cout << "exception : " << ex.what() << std::endl;
return 1;
}
catch(...)
{
std::cout << "unhandled exception" << std::endl;
return 1;
}
}