Могу ли я использовать динамический массив в качестве имени типа шаблона C++?

Что касается кода ниже:

template<typename PatternType>
cl_int enqueueFillBuffer(
    const Buffer& buffer,
    PatternType pattern,
    ::size_t offset,
    ::size_t size,
    const VECTOR_CLASS<Event>* events = NULL,
    Event* event = NULL) const
{
    cl_event tmp;
    cl_int err = detail::errHandler(
        ::clEnqueueFillBuffer(
            object_, 
            buffer(),
            static_cast<void*>(&pattern),
            sizeof(PatternType), 
            offset, 
            size,
            (events != NULL) ? (cl_uint) events->size() : 0,
            (events != NULL && events->size() > 0) ? (cl_event*) &events->front() : NULL,
            (event != NULL) ? &tmp : NULL),
            __ENQUEUE_FILL_BUFFER_ERR);

    if (event != NULL && err == CL_SUCCESS)
        *event = tmp;

    return err;
}

Код можно скомпилировать, если длина массива 6 определена как статическая.

queue.enqueueFillBuffer<float[6]>(buffer, nodes, 2345, 123456);

Мой вопрос: как сделать длину 6 переменной и передать компиляцию? Поскольку динамический массив поддерживается в C99, sizeof(float[n]) может правильно получить размер (для кода sizeof(PatternType)). Но я не могу заставить приведенный ниже код пройти компиляцию:

int n = 6;
queue.enqueueFillBuffer<float[n]>(buffer, nodes, 2345, 123456);

person Mike Zhang    schedule 29.05.2015    source источник
comment
n не является константой времени компиляции, поэтому компилятор не может определить тип статического массива во время компиляции.   -  person Austin Brunkhorst    schedule 29.05.2015
comment
Было бы неплохо сократить фрагмент кода до минимума, необходимого для понимания вашего вопроса. Для вашего примера вы можете указать пустую функцию. Этого действительно достаточно!   -  person Klaus    schedule 29.05.2015
comment
Да, компилятор не может вывести статический массив, но почему он не может распоряжаться им в виде динамического массива.   -  person Mike Zhang    schedule 29.05.2015
comment
Я оставляю за собой весь фрагмент кода, потому что это заголовочный файл сторонней библиотеки, и я думаю, что это дефект дизайна.   -  person Mike Zhang    schedule 29.05.2015
comment
Насколько я знаю, в С++ нет такой вещи, как динамический массив (некоторые компиляторы предлагают это как расширения).   -  person Walter    schedule 29.05.2015
comment
Сколько возможных значений может принимать n?   -  person Jarod42    schedule 29.05.2015
comment
Я знаю, что вы просто хотите сделать частичную специализацию для значения n, верно?   -  person Mike Zhang    schedule 30.05.2015


Ответы (2)


Рассмотрите возможность использования std::array. В более общем случае предположим, что вашему методу будет передан контейнер, подобный STL. Например,

std::array<float, 6> nodes;
nodes[0] = ...

or

std::vector<float> nodes;
nodes.resize(6);
nodes[0] = ...

Затем строки

static_cast<void*>(&pattern),
sizeof(PatternType),

может быть заменен на

static_cast<void*>(pattern.data()),
sizeof(typename PatternType::value_type) * pattern.size(), 

Затем компилятор может вывести тип, поэтому вызов метода просто становится

queue.enqueueFillBuffer(buffer, nodes, 2345, 123456);

Нет необходимости в явных аргументах шаблона.

person rwols    schedule 29.05.2015
comment
О, нет. Код static_cast‹void*›(&pattern), sizeof(PatternType) изменить нельзя. Это из заголовочного файла OpenCL 1.2 C++ Wrapper. Это просто ключ к проблеме. Я думаю, что это дефект конструкции. Я не знаю, видит ли это член Khronos Group. - person Mike Zhang; 29.05.2015
comment
Ах я вижу. Я предполагаю, что вы используете этот заголовочный файл. Вы можете раскошелиться и изменить его, иначе я не вижу решения. - person rwols; 29.05.2015
comment
Майк, динамический массив в этом случае определенно недействителен, потому что компилятор не может определить размер аргумента шаблона. Я видел ваше сообщение об ошибке в Khronos, но если вы внимательно прочитаете спецификацию OpenCL, вы заметите, что тип шаблона должен быть одним из встроенных типов: шаблон данных должен быть скалярным или векторным целым числом или типом данных с плавающей запятой. поддерживается OpenCL, как описано в разделах 6.1.1 и 6.1.2. Хотя результат должен быть таким же, действительно недопустимо передавать массив, как вы пытаетесь сделать. - person Lee; 29.05.2015
comment
@Lee прав, см. стр. 85 этого PDF-файла. Короче говоря, он говорит, что вы, по-видимому, должны использовать типы cl_*. Но, с другой стороны, эти типы являются просто определениями типов для обычных float, double и т. д., поэтому теоретически вы должны иметь возможность работать с std::vector<cl_float4> или std::vector<cl_float4>. - person rwols; 29.05.2015
comment
В спецификации сказано, что максимальное значение pattern_size — это размер наибольшего целочисленного или векторного типа данных с плавающей запятой, поддерживаемого устройством OpenCL. Это означает, что размер шаблона составляет ulong16, максимум 128 байт. std::vector использовать нельзя. - person Mike Zhang; 29.05.2015

Ответ - нет способа закончить это. Что касается реализации enqueueFillBuffer, см.: https://www.khronos.org/bugzilla/show_bug.cgi?id=1347 максимальный поддерживаемый размер шаблона: ulong16, 128 байт.

person Mike Zhang    schedule 30.05.2015