Проблема с шаблонами C ++ - PullRequest
3 голосов
/ 24 июля 2010

Я пытаюсь собрать небольшую библиотеку логгеров.Я сталкиваюсь с некоторой проблемой с шаблонами c ++.Вот как выглядит моя классовая структура.

class abstract_logger_t  {
public:
  typedef abstract_logger_t logger_type;
  template<typename data_t>
  abstract_logger_t& log(const data_t& data)  {
    return *this;
  }
};

class stdout_logger_t : public abstract_logger_t  {
public:
  typedef stdout_logger_t logger_type;
  template<typename data_t>
  stdout_logger_t& log(const data_t& data)  {
    cout << data << endl;
    return *this;
  }
};


template<typename logger_t, typename data_t>
void output(logger_t& logger, const data_t& data)  {
  static_cast<typename logger_t::logger_type&>(logger).log(data);
  cout << data;
}


template<typename data_t>
abstract_logger_t& operator<< (abstract_logger_t& logger, const data_t& data)  {
  output(logger, data);
  return logger;
}


stdout_logger_t logger;
logger << "Hi " << 1;

Здесь я ожидаю, что stdout_logger_t :: log будет вызываться выводом.но похоже, что производный тип теряется, а abstract_logger_t :: log заканчивается вызовом.Может кто-нибудь сказать мне, если я делаю что-то не так?

Ответы [ 3 ]

2 голосов
/ 24 июля 2010

Нет необходимости усложнять вещи, чем они должны быть.Наследие здесь бесполезно, если только вы не хотите использовать виртуальные методы, и в этом случае вы не будете широко использовать шаблоны.Вот обновленная версия вашего кода.Просто добавьте другие классы регистратора, когда вам нужны новые.

class stdout_logger_t 
{
public:
  typedef stdout_logger_t logger_type;
  template<typename data_t>
  logger_type& log(const data_t& data)  {
    cout << data << endl;
    return *this;
  }
};
class lazy_logger_t 
{
public:
  typedef lazy_logger_t logger_type;
  template<typename data_t>
  logger_type& log(const data_t& data)  {
    return *this;
  }
};    
template<typename logger_t, typename data_t>
void output(logger_t& logger, const data_t& data)  {
  logger.log(data);
}
template<typename logger_t, typename data_t>
logger_t& operator<< (logger_t& logger, const data_t& data)  {
  output(logger, data);
  return logger;
}

stdout_logger_t logger;
lazy_logger_t lazyLogger;
logger << "Hi " << 1;
lazyLogger << "Hi " << 1;

Будьте осторожны, я уверен, что эта система регистратора не будет работать с std :: endl.

1 голос
/ 24 июля 2010
template<typename data_t>
abstract_logger_t& operator<< (abstract_logger_t& logger, const data_t& data)  {
  output(logger, data);
  return logger;
}

Здесь, что бы вы ни указали, logger, компилятор преобразует его в abstract_logger_t&. Вы должны сделать первый аргумент также шаблонным.

template<typename T, typename data_t>
T& operator<< (T& logger, const data_t& data)  {
  output(logger, data);
  return logger;
}
0 голосов
/ 24 июля 2010

Кажется, вы путаете шаблоны с полиморфизмом времени выполнения. Кроме того, ваш класс abstract_logger_t не является абстрактным. Вы вызываете вывод оператора << с logger_t = abstract_logger_t. Параметр шаблона определяется путем проверки статических типов, а не динамических типов. Вывод аргумента шаблона и его создание являются механизмами времени компиляции. Это должно ответить на ваш вопрос. </p>

Кстати: соглашение заключается в использовании имен CamlCase для параметров шаблона.

...