Построение по умолчанию типа аргумента шаблона из класса шаблона

У меня есть следующий пример пользовательской специализации алгоритма std::set_union<...>. Я адаптировал реализацию с http://en.cppreference.com/w/cpp/algorithm/set_union.

Причина, по которой мне нужно настроить реализацию, заключается в том, что я хочу создать пары элементов из обоих наборов. В случае, когда диапазоны перекрываются (пересечение), выходные данные будут содержать std:: pair<* first_iter, * second_iter>

Там, где элементы уникальны для первого набора, выходные данные будут концептуально std:: pair<* first_iter, second_type ()> и, наконец, там, где элементы уникальны для второго набора, выходные данные будут std:: pair,

Код работает, однако в моей настройке мне пришлось жестко кодировать тип LoadableFile, чтобы создать элементы по умолчанию для обеих сторон std::pair<> (в зависимости от 2 из 3 случаев для специализации выше). Есть ли какой-нибудь способ доступа к информации о типе из аргумента шаблона Merge, чтобы узнать его тип (это PairMaker и конструкция по умолчанию Loadable(), не прибегая к жесткому кодированию специализации?

Это моя настройка:

// customized set_union that merges elements from both sets
// when the elements are unique in InputIt1 - merge constructs
// a pair with a default constructed type of InputIt1
template<typename InputIt1, typename InputIt2,
    typename OutputIt, typename Compare, 
    typename Merge>
OutputIt custom_set_union(
    InputIt1 first1, InputIt1 last1,
    InputIt2 first2, InputIt2 last2,
    OutputIt d_first, Compare comp,
    Merge merge)
{
    // example implementation taken and modified from cppreference.com
    for (; first1 != last1; ++d_first) {
        // empty second set
        if (first2 == last2) {
            // return std::copy(first1, last1, d_first);
            // equivalent of std::copy(...) from cppreference.com
            while (first1 != last1) {
                //*d_first++ = *first++;
                *d_first++ = merge(*first1++, LoadableFile());
            }
            return d_first;
        }
        if (comp(*first2, *first1)) {
            //*d_first = *first2++;
            *d_first = merge(LoadableFile(), *first2++);
        } else {
            //*d_first = *first1;
            // @JC note added *first2 as merge arg2 - overlapping region
            *d_first = merge(*first1, *first2);
            if (!comp(*first1, *first2))
                ++first2;
            ++first1;
        }
    }
    // return std::copy(first2, last2, d_first);
    // equivalent of std::copy(...) from cppreference.com
    while (first2 != last2) {
        //*d_first++ = *first++;
        *d_first++ = merge(LoadableFile(), *first2++);
    }
    return d_first;
};

Чтобы обеспечить необходимую структуру, чтобы сделать элементы подходящими для OutputIt - у меня есть класс Merge, который делает пары подходящими для OutputIt следующим образом:

/**
 * PairMaker helper struct to make pairs of objects from
 * 2 different types of sets templated on types A & B
 * must have default constructors - pair types A & B must
 * have default constructors
 */
template<typename A, typename B>
struct PairMaker {
    std::pair<A, B> operator() (const A& a, const B& b) const {
        return std::make_pair(a, b);
    }
};

и в моем случае, чтобы фактически использовать специализацию, я называю это следующим образом:

    auto comp = [](const LoadableFile& lhs, const LoadableFile& rhs) {
        return lhs.getRelativePath().filename() < rhs.getRelativePath().filename();
    };

    PairMaker<LoadableFile, LoadableFile> pairMaker;
    std::set<std::pair<LoadableFile,LoadableFile>> resultSet;
    custom_set_union(rLocalFileInfo.cbegin(), rLocalFileInfo.cend(),
        rModuleFileInfo.cbegin(), rModuleFileInfo.cend(), 
        std::inserter(resultSet, resultSet.end()),
        comp, pairMaker);

0 ответов

Другие вопросы по тегам