Я думаю, что вы имеете в виду глубокие, а не мелкий, операция - различие обычно используются для копий, но я предполагаю, что есть нет причин, по которым он не может применяться к другим операциям.
Для реализации этого вам потребуется специализированная специализация - иметь общий пример того, как зеркалировать общие типы (ничего не делать) и специализированный случай для зеркального отображения std::pair
.
К сожалению, специализация шаблона работает только для классов, а не для автономных функций, поэтому вам нужно написать класс шаблона, чтобы иметь (статическую) функцию-член, а затем, возможно, использовать неспециализированную функцию шаблона для вызова этого шаблона class static method - если вы хотите написать более простые вызовы, не беспокоясь о классе, в другом месте.
Ниже приведена полностью протестированная программа, включающая «глубокий» сброс на основе шаблона бонуса на основе std::pair
.
#include <iostream>
#include <utility>
template<typename T> struct Mirror // General case
{
typedef T input_t;
typedef T output_t;
static T mirror (T p) { return p; }
//static T mirror (T &&p) { return std::move (p); }
};
template<typename A, typename B> struct Mirror<std::pair<A,B>> // Special case
{
typedef typename Mirror<A>::output_t mirror_a_t;
typedef typename Mirror<B>::output_t mirror_b_t;
typedef std::pair<A,B> input_t;
typedef std::pair<mirror_b_t,mirror_a_t> output_t;
static output_t mirror (std::pair<A,B> p)
{
return std::make_pair (Mirror<B>::mirror (p.second), Mirror<A>::mirror (p.first));
}
};
template<typename T> auto mirror (T p) -> decltype (Mirror<T>::mirror (p))
{
return Mirror<T>::mirror (p);
}
template<typename T> struct Dump
{
static void dump (T p, unsigned p_Depth)
{
for (unsigned i = 0; i < p_Depth; i++) { std::cout << " "; }
std::cout << p << std::endl;
}
};
template<typename A, typename B> struct Dump<std::pair<A,B>>
{
static std::pair<A,B> dump (std::pair<A,B> p, unsigned p_Indent)
{
for (unsigned i = 0; i < p_Indent; i++) { std::cout << " "; }
std::cout << "begin first" << std::endl;
Dump<A>::dump (p.first, p_Indent + 1);
for (unsigned i = 0; i < p_Indent; i++) { std::cout << " "; }
std::cout << "end first" << std::endl;
for (unsigned i = 0; i < p_Indent; i++) { std::cout << " "; }
std::cout << "begin second" << std::endl;
Dump<B>::dump (p.second, p_Indent + 1);
for (unsigned i = 0; i < p_Indent; i++) { std::cout << " "; }
std::cout << "end second" << std::endl;
}
};
template<typename T> void dump (T p)
{
Dump<T>::dump (p, 0);
}
int main()
{
auto x1 = std::make_pair (std::make_pair ("hello", 5), 10.0);
auto x2 = mirror (x1);
std::cout << "--------------------" << std::endl;
std::cout << "Input" << std::endl;
std::cout << "-----" << std::endl;
dump (x1);
std::cout << "--------------------" << std::endl;
std::cout << "Output" << std::endl;
std::cout << "------" << std::endl;
dump (x2);
std::cout << "--------------------" << std::endl;
return 0;
}
Выходной ...
--------------------
Input
-----
begin first
begin first
hello
end first
begin second
5
end second
end first
begin second
10
end second
--------------------
Output
------
begin first
10
end first
begin second
begin first
5
end first
begin second
hello
end second
end second
--------------------
Некоторые пункты отметить ...
В ранних непроверенных и сломанные версии, я включил некоторую поддержку ходу семантики. Я прокомментировал это здесь, потому что я даже не потрудился пропустить по ссылке в другом месте - для простоты все передается по значению и сосредоточено на специализированной специализации. Здесь определенно избыточное копирование, которое я не потрудился оптимизировать.
Глубоко отраженный тип std::pair<A,B>
обычно не std::pair<B,A>
, потому что компоненты также отражаются. Вот почему шаблоны Mirror
имеют различные typedefs - определение правильного рекурсивно-отраженного типа.
Функция шаблона mirror
не являющийся членом использует косой тип возвращаемого значения - я думаю это необходимо, хотя ТВНА я не пробовал без него.
Еще раз спасибо Jarod42 за то, что вы указали одну из ошибок в более ранней версии.
Последнее замечание: поскольку «глубокие» операции имеют тенденцию работать настолько глубоко, насколько это возможно, они могут идти глубже, чем вы ожидаете, если вы находитесь в более широком контексте шаблонов. Вы можете зеркалируете -О типа std::pair
где ваши глубочайшие элементы являются A
, B
, C
и т.д. - аргументы типа для шаблона - и забывать, что, возможно, A
, B
и т.д. сам по себе могут быть std::pair
экземпляров (в зависимости от шаблонов вызывающего абонента), который не должны быть зеркальным.
Это может быть обработано путем обертывания значений барьерами для глубоких операций, но это может быть так же просто, как использование мелких операций для создания более крупных полу-глубоких операций, которые работают с фиксированной глубиной.
Извините за задержку.
это mehtod может, т обрабатывать все, что T1 = T2, где T1, T2 являются типами паров –
! Вероятно, вы можете определить, является ли один параметр шаблона парой (у него есть first_type и second_type typedefs), а затем вы можете сделать рекурсивный вызов. Но это на самом деле не гарантирует, что параметр является парным ... я не уверен, что его можно решить красивым и безопасным способом. – Melkon