Создание нескольких шаблонов - PullRequest
1 голос
/ 18 июня 2011

Если у меня есть класс с именем Tuple<T, SIZE> и я хочу, скажем, 20 различных шаблонов с плавающей точкой, создаваемых при компиляции библиотеки (чтобы у пользователя не возникало ошибок компоновки):

template Tuple<float, 1>;
template Tuple<float, 2>;
...
template Tuple<float, 20>;

IsЕсть ли способ рекурсивного выполнения вышеизложенного?И, может быть, позволить ему быть гибким, чтобы я мог написать любое число, которое бы мне понравилось, и оно создало для меня экземпляры классов?

РЕДАКТИРОВАТЬ: Что я пробовал до сих пор (не похожена работу):

template <typename T, unsigned int MAX_RANGE>
class AllTuples
{
  Tuple<T, MAX_RANGE> y;
  AllTuples<T, MAX_RANGE - 1> x;
};

template <typename T>
class AllTuples<T, 1>
{
  Tuple<T, 1> x;
};
AllTuples<float, 10>;

Ответы [ 3 ]

4 голосов
/ 18 июня 2011

Простите, вам не повезло Если вы не используете библиотеку метапрограммирования препроцессора (boost.pp), нет способа автоматизировать это. Не с шаблонным метапрограммированием.

То, что вы произвели, есть неявные экземпляры из Tuple<float, N>. Но неявные экземпляры имеют два важных отличия от явных

  1. Они не будут создавать все определения членов (создаются только те, которые нужны немедленно). Другие определения создаются только тогда, когда они используются.
  2. Неявное создание экземпляров использованных определений элементов не может использоваться в качестве источника определения для других единиц перевода.

Что касается последнего, так как я не знаю причину этого, я просто процитирую спецификацию.

Неэкспортированный шаблон должен быть определен в каждой единице перевода, в которой он создается неявно (14.7.1), если только соответствующая специализация явно не создана (14.7.2) в некоторой единице перевода; Диагностика не требуется.

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

1 голос
/ 18 июня 2011

Вы можете использовать некоторую магию шаблона для форсирования этого экземпляра:

namespace {
    template <unsigned N>
    struct Instantiator {
        void instantiate_members(const Tuple<float,N>& tuple, Instantiator<N-1>) {
            // use **all** member functions here
            // so that they get instantiated
        }

    template <>
    struct Instantiator<0> {}
}

А затем создать экземпляр этого шаблона:

template class Instantiator<20>;

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

0 голосов
/ 18 июня 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...