Template class: ctor vs. & # 8594; new C ++ standard

in this question:
template; Point <2, double>; Point <3, double>
Dennis and Michael spotted an unreasonably stupidly implemented constructor.
They were right, I did not consider it at that moment. But I found out that the constructor doesnโ€™t help much for a template class like this, instead the function here is much more convenient and safer

namespace point { template < unsigned int dims, typename T > struct Point { TX[ dims ]; std::string str() { std::stringstream s; s << "{"; for ( int i = 0; i < dims; ++i ) { s << " X" << i << ": " << X[ i ] << (( i < dims -1 )? " |": " "); } s << "}"; return s.str(); } Point<dims, int> toint() { Point<dims, int> ret; std::copy( X, X+dims, ret.X ); return ret; } }; template < typename T > Point< 2, T > Create( T X0, T X1 ) { Point< 2, T > ret; ret.X[ 0 ] = X0; ret.X[ 1 ] = X1; return ret; } template < typename T > Point< 3, T > Create( T X0, T X1, T X2 ) { Point< 3, T > ret; ret.X[ 0 ] = X0; ret.X[ 1 ] = X1; ret.X[ 2 ] = X2; return ret; } template < typename T > Point< 4, T > Create( T X0, T X1, T X2, T X3 ) { Point< 4, T > ret; ret.X[ 0 ] = X0; ret.X[ 1 ] = X1; ret.X[ 2 ] = X2; ret.X[ 3 ] = X3; return ret; } }; int main( void ) { using namespace point; Point< 2, double > p2d = point::Create( 12.3, 34.5 ); Point< 3, double > p3d = point::Create( 12.3, 34.5, 56.7 ); Point< 4, double > p4d = point::Create( 12.3, 34.5, 56.7, 78.9 ); //Point< 3, double > p1d = point::Create( 12.3, 34.5 ); //no suitable user defined conversion exists //Point< 3, int > p1i = p4d.toint(); //no suitable user defined conversion exists Point< 2, int > p2i = p2d.toint(); Point< 3, int > p3i = p3d.toint(); Point< 4, int > p4i = p4d.toint(); std::cout << p2d.str() << std::endl; std::cout << p3d.str() << std::endl; std::cout << p4d.str() << std::endl; std::cout << p2i.str() << std::endl; std::cout << p3i.str() << std::endl; std::cout << p4i.str() << std::endl; char c; std::cin >> c; } 

Does the new C ++ standard have any new improvements, language features or simplifications regarding this aspect of the ctor template class?
what do you think about implementing a combination of namespace, stuct, and create?
thank you very much in advance
Unfortunately,

+1
c ++ function constructor templates
May 08 '10 at 2:09
source share
2 answers

Yes, as Michael noted in his answer to your previous question, in C ++ 0x you can use the list of initializers to pass an arbitrary number of arguments to your ctor. In your case, the code will look something like this:

 template <int dims, class T> class point { TX[dims]; public: point(std::initializer_list<T> const &init) { std::copy(init.begin(), init.begin()+dims, X); } }; 

You can create a point feature with this:

 point<3, double> x{0.0, 0.0, 0.0}; 

Personally, I'm not sure that I like the basic design. In particular, I would prefer that X turn into std::vector and determine the number of dimensions strictly from the parameter list that was passed instead of having it as a template argument:

 template <class T> class point { std::vector<T> X; public: point(std::initializer_list<T> init) { std::copy(init.begin(), init.end(), std::back_inserter(X)); } }; 

It has some tradeoffs though - points with a different number of dimensions remain the same type. For example, he basically claims that it is wise to assign a two-dimensional point to a 3D point, or vice versa.

+1
May 08 '10 at 2:49 p.m.
source share

Since the array is publicly available, it can omit the constructor and allow aggregate initialization (e.g. boost::array<T, N> ).

 Point<2, int> p = {1, 2}; 

This is no worse than calling the create function. (The create function can be convenient as a utility.)




In C ++ 0x, you can have all kinds of cool. For example, play with variable templates to check it at compile time if the constructor is called with the correct number of arguments. (The following can also check if the arguments ...U all of type T , with even more metaprogramming, but this may be absolutely optional.)

 //helper to copy variable amount of arguments into an array namespace detail { template <class T, class U> void copy_variadic(T* p, U value) { *p = value; } template <class T, class First, class ...Rest> void copy_variadic(T* p, First var, Rest ...args) { *p = var; copy_variadic(++p, args...); } } //detail template < unsigned int dims, typename T > struct Point { TX[ dims ]; Point() : X{} { } template <class ...U> Point(U... args) { static_assert(sizeof...(args) == dims, "Too many or too few arguments to Point constructor"); detail::copy_variadic(X, args...); } //... }; 

(Actually, with some changes - great redirection - copy_variadic will make a nice addition to my collection of Variadic-template utilities if someone doesnโ€™t come and indicate a much better way.)

+4
May 08 '10 at 2:59
source share



All Articles