template class: ctor against function -> new C++ standard

后端 未结 2 1070
半阙折子戏
半阙折子戏 2021-01-16 02:21

in this question:
template; Point<2, double>; Point<3, double>
Dennis and Michael noticed the unreasonable foolishly implemented constructor.
They we

相关标签:
2条回答
  • 2021-01-16 02:56

    Yes, as Michael pointed out in his answer to your previous question, in C++0x you'll be able to use an initializer list to pass an arbitrary number of arguments to your ctor. In your case, the code would look something like:

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

    You could create a point object with this something like:

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

    Personally, I'm not sure I like the basic design very well though. In particular, I'd rather see X turned into an 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));
        }
    };
    

    This does have some trade-offs though -- points with a different number of dimensions are still the same type. For example, it basically asserts that it's reasonable to assign a 2D point to a 3D point, or vice versa.

    0 讨论(0)
  • 2021-01-16 03:02

    Since the array is public, it is an option to omit the constructor and allow aggregate initialization (like boost::array<T, N> for example).

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

    This is no worse than having to call a create function. (The create function might still be handy as a utility.)


    In C++0x you will be able to have all sorts of coolness. For example, play with variadic templates, to have it checked at compile-time if the constructor is called with a right number of arguments. (The following could also check if the arguments ...U are all of type T, with some more metaprogramming fun, but it might not be absolutely necessary.)

    //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 {
    
        T X[ 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 modifications - perfect forwarding - copy_variadic would make a nice addition to my collection of variadic-template utilities, if someone doesn't come and point out a significantly better way.)

    0 讨论(0)
提交回复
热议问题