October 22, 2024
Chicago 12, Melborne City, USA
templates

How to handle datatypes from various containers in templated classes deriving values from the container's elements?


I try to find a sane way to support custom ID datatypes for classes being based on various input datatypes. What does that mean?

Assume we have several possible data records D of type TD from which we can derive an ID of type TI. These data records live in all kinds of containers. Some examples:

  • std::vector<int>
  • std::set<double>
  • A C-array given by pointer/size, i.e. const float* p and size_t s

From all these containers, we can derive an ID for its elements. Furthermore, there is a class Dummy that requires to store these IDs internally. I want to prevent unnecessary copies by all means which is why I do not want the user of Dummy to first create the ID container himself and then copy it to the Dummy-constructor.

My first idea was to create the ID container on caller side and then move it into the Dummy constructor. I cannot say precisely why but this felt wrong to me (really, it is only a gut feeling).

Finally, I decided to go for a solution to pass an iterator to the caller’s container and a little callback being able to compute the ID for each element (see code below).

This solution works, but it is not really nice because template argument deduction does not work here. This means, I always have to write down the target ID type twice – at the Dummy-constructor and at some point in the callback.

Overall: Is there a better solution than this? Can I improve my idea to get rid of the "duplicated datatype problem"?

#include <string>
#include <vector>   

template<typename IdType>
struct Dummy {
    template<typename InputIt, typename Converter>
    Dummy(InputIt first, InputIt last, Converter convert) {
        for (auto it = first; it != last; ++it) {
            _ids.push_back(convert(*it));
        }
    }
    std::vector<IdType> _ids;
};

int main() {
    std::vector<int> c1{1, 2, 3, 4, 5};
    auto d1 = Dummy<std::string>(c1.begin(), c1.end(), [](const auto& c) { return std::to_string(c); });

    std::pair<double, double> c2[2] = {{1.0, 2.0}, {3.0, 4.0}};
    auto d2 = Dummy<uint32_t>(c2, c2 + 2, [](const auto& c) { return static_cast<uint32_t>(c.first * c.second); });
}



You need to sign in to view this answers

Leave feedback about this

  • Quality
  • Price
  • Service

PROS

+
Add Field

CONS

+
Add Field
Choose Image
Choose Video