Построение по умолчанию типа аргумента шаблона из класса шаблона
У меня есть следующий пример пользовательской специализации алгоритма 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
Это моя настройка:
// 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);