Я работаю над фреймворком, который поможет в создании шаблонов функций. У меня есть куча функций, шаблонных по целочисленному значению для целей оптимизации, которые необходимо создать и выбрать во время выполнения. Пример использования заключается в следующем:Нужна помощь Очистка шаблона Мгновенная структура
// Function to instantiate templates of.
template<int a, int b, int c> void MyFunction(float, double){};
// List of values to substitute into each template parameter.
typedef mpl::vector_c< int, 7, 0, 3, 4, 2> valuesToInstantiate;
int numberOfValuesPerParameter = size<valuesToInstantiate>::type::value;
// Function pointer type. Must define type for array to hold template instantiations.
typedef void (*MyFunctionPointer)(float, double);
// Array to hold template instantiations.
// Accessed at runtime to get proper instantiation.
MyFunctionPointer arrayOfTemplateInstantiations[numberOfValuesPerParameter*numberOfValuesPerParameter*numberOfValuesPerParameter];
// Passed to template instantiation framework.
// AddTemplate member function will be called once per template value combo (3 int values).
// templateIndex indicates where to store the instantation in the array.
// templateSequence contains the template value combo (3 int values).
template<int templateIndex, typename templateSequence>
struct MyFunctionTemplateCreator
{
static void AddTemplate(void)
{
// Store template instantiation in array.
arrayOfTemplateInstantiations[templateIndex] = MyFunction
<
mpl::at<templateSequence, mpl::int_<0> >::type::value,
mpl::at<templateSequence, mpl::int_<1> >::type::value,
mpl::at<templateSequence, mpl::int_<2> >::type::value
>;
}
};
// List of lists where each inner list contains values to instantiate
// for the corresponding template parameter. E.g. each value in the first
// inner list will be passed into the first template parameter of MyFunction
typedef mpl::vector< valuesToInstantiate, valuesToInstantiate, valuesToInstantiate > templatesToCreate;
// Call template instantation framework to instantiate templates.
CreateTemplates<MyFunctionTemplateCreator, templatesToCreate> unusedVariable;
// Call proper template instantation at runtime...using index 5 arbitrarily for example.
arrayOfTemplateInstantiations[5](1.5, 2.0);
Таким образом, в этом примере, я инстанцировании Моя_функция, который принимает целые значения 3, с каждой комбинацией { {7, 0, 3, 4, 2}, {7, 0, 3, 4, 2}, {7, 0, 3, 4, 2} }
. Я опустил реализацию CreateTemplates, поскольку он довольно длинный, но он реализован с использованием boost MPL for_each. Код, указанный выше, необходим для каждой функции, с которой я хочу это сделать, и, хотя она короче, чем запись явных экземпляров 512, это еще немного.
Удивительно, но самый длинный код, который должен быть записан для каждой функции, с которой я хочу это сделать, - это typedef указателя функции, так как многие из функций принимают 10 + аргументы. Есть ли способ сохранить эти экземпляры шаблонов в массиве более общего типа, каким-то образом обернув их?
Для аргументации можно предположить, что параметры шаблона всегда являются целыми значениями, такими как пример, так что сигнатуры экземпляров шаблона одинаковы для заданного шаблона функции. Выполняемые функции - это все в глобальном пространстве имен, никогда не функционируют в качестве членов (они на самом деле являются ядрами CUDA). Любые другие советы по его очистке будут оценены по достоинству.
Примечание: С помощью C++ 03
Edit: Я хотел бы задать вопрос, TarmoPikaro по поводу того, что я пытаюсь сделать.
Я работаю с приложением, в котором до 4 задач/потоков будет делиться графическим процессором для выполнения своей работы (такая же работа, разные данные). Поскольку некоторые из наших ядер CUDA используют текстуры, нам необходимо динамически раздавать доступные текстуры во время выполнения. Мы задерживаем поддержку унаследованных возможностей CUDA, потому что объекты текстуры не могут передаваться как аргументы функции и должны быть статическими глобальными переменными. Выдавать текстуры для процессора задач/нитей затем, мы выдаем индексы текстуры и наши CUDA ядро имеет такие заявления:
// (variables t_int_2d_N are texture objects)
if (maskTextureIndex == 0)
maskValue = tex2D(t_int_2d_0, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 1)
maskValue = tex2D(t_int_2d_1, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 2)
maskValue = tex2D(t_int_2d_2, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 3)
maskValue = tex2D(t_int_2d_3, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 4)
maskValue = tex2D(t_int_2d_4, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 5)
maskValue = tex2D(t_int_2d_5, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 6)
maskValue = tex2D(t_int_2d_6, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
else if (maskTextureIndex == 7)
maskValue = tex2D(t_int_2d_7, (float(p) + 0.5f)*maskScale.x + maskShift.x, (float(q) + 0.5f)*maskScale.y + maskShift.y)
Имея это утверждение в цикле в ядре неприемлемых потери производительности. Чтобы избежать потери производительности, мы подбираем ядро по целочисленному значению (представляющему индекс текстуры) таким образом, что приведенный выше условный оператор компилируется. Ядро, которое содержит вышеуказанный код, будет создаваться с помощью maskTextureIndex, равным 0-7, поэтому у нас есть 8 разных ядер для выбора из среды выполнения. В некоторых наших ядрах используется до трех текстур, и мы допускаем каждый тип текстуры (например, float 1D, float 2D, float2 2D, int 3D и т. Д.), Чтобы иметь индексы 0-7, что означает, что мы должны создать экземпляр 8 * 8 * 8 = 512 различных ядер для компиляции трех разных условных операторов, подобных приведенным выше. Код в моем исходном вопросе используется для каждого ядра, использующего текстуры, чтобы создать экземпляр всех комбинаций.
К сожалению, это так, что сам язык программирования может быть адаптирован каким-либо образом, о котором не говорили сами авторы языка программирования. Такое злоупотребление или злоупотребление языком возможно для экстремальных программистов, которые думают, что достигли Гайи и могут делать все, что захотят, с помощью языка. К сожалению, такой код становится сложным для дальнейшего развития и дальнейшего развития, и очень возможно, что во время последующих итераций другой разработчик, скорее всего, перепишет ваше решение. Может быть, вы можете более подробно указать, чего вы хотите достичь в конце? – TarmoPikaro
@TarmoPikaro Наконец-то обратился к вашему вопросу. Не уверен, что есть лучшее решение без обновления до C++ 11. Надеюсь, что кто-то возьмет это как вызов;). – user1777820