tags:

views:

113

answers:

1

I am not sure if title makes sense.

let me explain what I want to do:

I have template constructor, the argument generally must be reference, but can be value in certain cases. Ultimately, I would like to have something like:

matrix_adapter(typename adaptable<T,A>::type);

where adaptable<T,A>::type can either be value or reference defending on type of A. I am not able to do so (template instantiation does not happen), and unsure why.

Right now, my solution is to enable/disable constructor using Sfinae:

matrix_adapter(A a, typename adaptable<T,A>::pass_by_value = 0)

however, that requires two constructors which are essentially the same.

Is it possible to do it using one generic constructor?

more code:

template<typename T>
struct adaptable<T, boost::detail::multi_array::const_sub_array<T, 2, const T*> >
{
    typedef void* pass_by_value;
    typedef boost::detail::multi_array::const_sub_array<T, 2, const T*> type;
    static size_t size1(const type &A) { return A.shape()[0]; }
    static size_t size2(const type &A) { return A.shape()[1]; }
    static const T* data(const type &A) { return A.origin(); }
};

template<typename T, class L = ublas::column_major>
struct matrix_adapter
    : ublas::matrix<T, L, ublas::array_adaptor<T> >
{
    typedef ublas::array_adaptor<T> array_type;
    typedef ublas::matrix<T, L, array_type> base;
    matrix_adapter(size_t size1, size_t size2, T *data)
        : base(size1, size2, array_type(size1*size2, pointer()))
    {
        initialize(data);
    }

    template<class A>
    matrix_adapter(A a, typename adaptable<T,A>::pass_by_value = 0)
        : base(adaptable<T,A>::size1(a),
               adaptable<T,A>::size2(a),
               array_type(adaptable<T,A>::size1(a)*
                          adaptable<T,A>::size2(a),
                          pointer()))
    {
        initialize(adaptable<T,A>::data(a));
    }

    template<class A>
    matrix_adapter(A &a)
        : base(adaptable<T,A>::size1(a),
               adaptable<T,A>::size2(a),
               array_type(adaptable<T,A>::size1(a)*
                          adaptable<T,A>::size2(a),
                          pointer()))
    {
        initialize(adaptable<T,A>::data(a));
    }
+1  A: 

Your constructor is itself a template, but with a signature of matrix_adapter(typename adaptable<T,A>::type) the compiler cannot deduce the type of A from the call.

By using SFINAE you enable the compiler to deduce A from the first constructor argument, and then the second argument prevents one or other from being considered in the overload set.

I don't believe it is possible to eliminate either constructor.

Anthony Williams