Удаление квалификаторов с частичным созданием шаблона - PullRequest
0 голосов
/ 04 сентября 2018

Для реализации интерфейса, который принимает функцию обратного вызова и параметр,

Ex.

template<class T_class_type, class T_data_type>
class Some_interface
{
public:
  Some_interface(T_class_type* inst, void (T_class_type::*func)(T_data_type));
  void add(const T_data_type& data);
private:
  void call(const T_data_type& data);
};

, где T_data_type может быть любого типа и иметь квалификаторы const и &, у меня проблема, когда форма [T_data_type] = const T_data_type&. Например, в функции add() это расширилось бы до add(const const T_data_type&& data). Очевидная ошибка компилятора. Однако причина, по которой мы передаем постоянные ссылки, заключается в том, чтобы уменьшить ненужное копирование данных. Во всяком случае, чтобы решить эту проблему, я реализовал следующее,

template<class T_data_type>
struct No_qualifiers
{
  typedef T_data_type Type;
};

template<class T_data_type>
struct No_qualifiers<T_data_type&>
{
  typedef T_data_type Type;
};

template<class T_data_type>
struct No_qualifiers<const T_data_type>
{
  typedef T_data_type Type;
};

template<class T_data_type>
struct No_qualifiers<const T_data_type&>
{
  typedef T_data_type Type;
};

template<class T_class_type, class T_data_type>
class Some_interface
{
public:
  Some_interface(T_class_type* inst, void (T_class_type::*func)(T_data_type));
  void add(const typename No_qualifiers<T_data_type>::Type& data);
private:
  void call(const T_data_type& data);
};

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

Используя это на практике, я нахожу ошибки, которые не могу объяснить. Я был бы признателен за новый набор глаз, которые могут быть в состоянии увидеть предостережения при таком подходе.

Некоторые условия, которые у меня есть, состоят в том, что я не могу изменить способ, которым пользователи вызывают интерфейс, и я использую более старый стандарт с 2003 года. Ошибка, которую я сейчас отлаживаю, я полагаю, связана с typename, используемым в коде пользователя как Что ж; возможно, передача неразрешенного типа в add(), что также не разрешено, поэтому компилятор не может найти подходящую функцию для вызова.

Edit:

Таким образом, проблема "typename", с которой я столкнулся, была ошибкой кодирования, не связанной с вопросом. Кроме того, я обнаружил, что удаление спецификатора const не нужно, нужно удалить только &.

Спасибо за ответы.

1 Ответ

0 голосов
/ 04 сентября 2018

Стандарт уже дает вам std::remove_reference и std::remove_const то, что вы пытаетесь реализовать самостоятельно; typedef улучшает читабельность:

class SomeInterface
{
    using ArgType
        = typename std::remove_const<std::remove_reference<T>::type>::type;
    void add(ArgType const& data);
};

Чтобы использовать оба с вашим более старым компилятором, вы можете просто скопировать из разделов "возможная реализация" & ndash; тем не менее, я действительно рекомендую обновиться до более нового компилятора (если он доступен, конечно).

...