Search code examples
c++c++11vectorstlstxxl

Stxxl Vector as dropin replacement for std::vector


This is a followup of Vector of pairs with generic vector and pair type, template of template.

I'd like to be able to call a method with a std::vector or stxxl:vector, while template arguments of the vector (Pair of x,y) are specified.

Specifically the method signatrue might look like this:

template<typename t_x, typename t_y,
            template<typename, typename> class t_pair,
            template<typename...> class t_vector>
    method(t_vector<t_pair<t_x,t_y>> &v) 

Unfortunately when specifying the signature like this, it is not possible to pass a stxxl:vector as t_vector. It leads to the following compile error:

sad.hpp:128:5: note:   template argument deduction/substitution failed: 
program.cpp:104:52: error: type/value mismatch at argument 1 in template parameter list for ‘template<class ...> class t_vector’
         method(coordinates);
                           ^ 
program.cpp:104:52: error:   expected a type, got ‘4u’ 
program.cpp:104:52: error: type/value mismatch at argument 1 in template parameter list for ‘template<class ...> class t_vector’ 
program.cpp:104:52: error:   expected a type, got ‘2097152u’

The question is how to modify the method signature in order to be able to use stxxl::vector as a drop-in replacement for existing code using std::vector?

Update on why I'm using nested templates for the vector: I might be mistaken, but I'd like the compiler which types for the variables in the aforementioned method.

I'm for example building a vector or a queue

std::vector<t_x> intervals(k * k + 1);
typedef std::tuple<std::pair<t_x,t_y>,std::pair<t_x,t_y>, std::pair<t_x,t_y>, uint> t_queue;
std::queue <t_queue> queue;

Which should either be uint32_t or uint64_t depending on wether the type of the pair-elements is uint32_t or uint64_t


Solution

  • The problem is that stxxl::vector has non-type template parameter:

    BlockSize external block size in bytes, default is 2 MiB

    So it cannot be match against template <typename... >.

    You should not use a template template parameter in this case, something like this would be better (I think):

    template <typename t_vector>
    void method (t_vector &v) {
        typedef typename t_vector::value_type::first_type t_x;
        typedef typename t_vector::value_type::second_type t_y;
        // or in c++11 and above
        typedef decltype(v[0].first) t_xd;
        typedef decltype(v[0].second) t_yd;
    }
    

    In the above, you retrieve t_x and t_y either using:

    • value_type which is something that all Container should have (both std::vector and stxxl::vector have it);
    • decltype which directly gets the type from the expression v[0].first (works even if v is empty since the expression inside decltype is never evaluated).

    From my experience, it is better to use a very generic template argument and then retrieve information from it (value_type, decltype, ...) than trying to constraint the template argument itself with given types.