Шаблонная специализация C++ без функции по умолчанию

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

существует также вопрос вкуса. API могут соблюсти каждое правило в любом своде правил, и все еще высосать, из-за рабского соблюдения различных идеологий в моде. Недавний преступник является ориентацией шаблона, где Шаблоны "одиночка" (немного больше, чем инициализированные глобальные переменные) и Шаблоны "фабрика" (способ параметризовать конструкцию, но часто реализовываемый если не необходимый) злоупотребляются. В последнее время более вероятно, что Инверсия управления (IoC) и связала взрыв в количестве крошечных интерфейсных типов, которое добавляет избыточную концептуальную сложность к проектам.

лучшие обучающие программы для вкуса являются имитацией (читающий много кода и API, узнавая, какие работы и не работает), опыт (делающий ошибки и извлекающий уроки из него) и думающий (не просто сделайте то, что является модным ради самого себя, думайте перед действием).

28
задан 27 October 2009 в 08:25
поделиться

4 ответа

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

template<typename T>
T GetGlobal(const char *name) { T::unimplemented_function; }
// `unimplemented_function` identifier should be undefined

Если вы используете Boost, вы можете сделать его более элегантным:

template<typename T>
T GetGlobal(const char *name) { BOOST_STATIC_ASSERT(sizeof(T) == 0); }

Стандарт C ++ гарантирует, что не существует такого типа, который имеет sizeof равно 0, поэтому вы получите ошибку времени компиляции.

Как sbi предложил в своих комментариях, последнее может быть сокращено до:

template<typename T>
T GetGlobal(const char *name) { char X[!sizeof(T)]; }

Я предпочитаю первое решение, потому что оно дает больше четкое сообщение об ошибке (по крайней мере, в Visual C ++), чем другие.

25
ответ дан 28 November 2019 в 03:08
поделиться

Я бы посоветовал фактически не предоставлять реализацию, а просто декларировать метод.

Другой вариант - использовать утверждение во время компиляции. У Boost есть несколько таких чудовищ.

namespace mpl = boost::mpl;
BOOST_MPL_ASSERT((mpl::or_< boost::same_type<T, double>,
                            boost::same_type<T, int> >));

Есть также его версия сообщения, которая может помочь.

3
ответ дан 28 November 2019 в 03:08
поделиться

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

template<typename T>
struct GlobalGetter;

template<>
struct GlobalGetter<int> {
  static int GetGlobal(const char *name);
};

template<>
struct GlobalGetter<double> {
  static double GetGlobal(const char *name);
};

template<typename T>
T GetGlobal(const char *name)
{
  return GlobalGetter<T>::GetGlobal(name);
}
5
ответ дан 28 November 2019 в 03:08
поделиться

Ниже приведены методы, альтернативные использованию boost:

Объявление typedef для зависимого имени

Это работает, потому что поиск имени для DONT происходит только после замены 'T'. Это аналогичная (но легальная) версия примера, приведенного Кириллом

template <typename T>
T GetGlobal (const char * name) {
    typedef typename T::DONT CALL_THIS_FUNCTION;
}

Использование неполного возвращаемого типа

Этот метод не работает для специализаций, но он будет работать для перегрузок. Идея состоит в том, что законно объявить функцию, которая возвращает неполный тип, но не вызывать ее:

template <typename T>
class DONT_CALL_THIS_FUNCTION GetGlobal (const char * name);
2
ответ дан 28 November 2019 в 03:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: