Специализация шаблона функции, который принимает универсальный ссылочный параметр

Как специализировать шаблон функции, который принимает универсальный ссылочный параметр?

foo.hpp:

template<typename T>
void foo(T && t)    // universal reference parameter

foo.cpp

template<>
void foo<Class>(Class && class) {
    // do something complicated
}

Здесь Class больше не является выведенным типом и, таким образом, в точности является Class; это не может быть Class &, поэтому правила свертывания ссылок мне здесь не помогут. Возможно, я мог бы создать другую специализацию, которая принимает параметр Class & (я не уверен), но это подразумевает дублирование всего кода, содержащегося в foo, для каждой возможной комбинации ссылок rvalue/lvalue для всех параметров, что и предполагается универсальными ссылками. избежать.

Есть ли способ сделать это?

Чтобы быть более конкретным о моей проблеме, если есть лучший способ ее решить:

У меня есть программа, которая может подключаться к нескольким игровым серверам, и каждый сервер, по большей части, называет все одним именем. Тем не менее, у них есть немного разные версии для нескольких вещей. Есть несколько различных категорий, которыми могут быть эти вещи: перемещение, элемент и т. д. Я написал общий вид набора функций «переместить строку для перемещения перечисления» для вызова внутреннего кода, и мой код интерфейса сервера имеет аналогичный функции. Однако у некоторых серверов есть собственный внутренний идентификатор, с которым они взаимодействуют, некоторые используют строки, а некоторые используют и то, и другое в разных ситуациях.

Теперь я хочу сделать это немного более общим.

Я хочу иметь возможность вызывать что-то вроде ServerNamespace::server_cast<Destination>(source). Это позволило бы мне преобразовать Move в std::string или ServerMoveID. Внутренне мне может понадобиться сделать копию (или перейти), потому что некоторые серверы требуют, чтобы я сохранял историю отправленных сообщений. Универсальные ссылки кажутся очевидным решением этой проблемы.

Заголовочный файл, о котором я сейчас думаю, будет содержать следующее:

namespace ServerNamespace {

template<typename Destination, typename Source>
Destination server_cast(Source && source);

}

И файл реализации будет определять все допустимые преобразования как шаблонные специализации.


person David Stone    schedule 30.11.2012    source источник
comment
Должно ли f быть foo? Кроме того, каков контекст проблемы? Обычно вам нужны перегрузки, а не специализации.   -  person GManNickG    schedule 01.12.2012
comment
@GManNickG Возможно, я использовал неправильную терминологию. Я отредактировал свой вопрос, указав более подробную информацию о том, чего я пытаюсь достичь.   -  person David Stone    schedule 01.12.2012
comment
Для действительно хорошей статьи по этому вопросу см.: mortoray.com/2013/06/03/   -  person Ton van den Heuvel    schedule 30.11.2016


Ответы (2)


На мой взгляд, лучшим решением является использование системы отправки тегов, в которой вы перегружаетесь тегами, а не фактическим типом:

struct foo {
    struct tag {};
};

struct bar {
    struct tag {};
};

template<typename Destination, typename Source>
Destination server_cast(Source && source, foo::tag) {
    // foo
}

template<typename Destination, typename Source>
Destination server_cast(Source && source, bar::tag) {
    // bar
}

template<typename Destination, typename Source>
Destination server_cast(Source && source) {
    return server_cast<Destination>(std::forward<Source>(source), typename std::remove_reference<Source>::type::tag());
}
person Pubby    schedule 30.11.2012
comment
Мне придется подумать об этом еще немного. - person David Stone; 13.12.2012

Самое расширяемое, что можно сделать, это создать специализацию класса шаблона.

template< class X > struct Whatever {
    void f(){ ... }
};

template<> struct Whatever<UserType> {
    void f(){ ... }
};

Причина, по которой я говорю, что это наиболее расширяемый, заключается в том, что вы можете добавить специализацию где угодно, внутри или вне файла, который определяет Whatever.

Это дополнение, а не исключение для решения по отправке тегов, предложенного Pubby.

person SplinterOfChaos    schedule 30.11.2012