Как получить доступ к объектам специализации шаблона с помощью переменных

#c

Вопрос:

Название может не очень ясно выражать мой смысл

  1. Создал шаблон карты классов, типом которого является перечисление VertexType, и специализирую их
  2. существует векторный контейнер типа VertexType
  3. доступ к другому объекту карты через элемент в векторе
  4. Вопрос: как получить доступ к другому объекту шаблона через переменные вместо переключателя use,я попытался использовать тип i как для доступа к объекту ,очевидно, это не работает.я новичок в использовании c , и английский язык плохой, спасибо, что прочитали это
 // 1
template<VertexType> struct Map;
template<> 
struct Map<VertexType::Position2D>
{
    static constexpr DXGI_FORMAT dxgiFormat = DXGI_FORMAT_R32G32_FLOAT;
    static constexpr const char* semantic = "Position";
    static constexpr const UINT offset = 8;
};//There are other specialized versions
//VertexType is a enum class,include postion,color...```
//2
std::vector<VertexType> v;
//3
    UINT offset = 0;
    for (const auto amp;i : v)
    {
        switch (i)  // i is a VertexType::...
        {
        case VertexType::Position2D:
        {
            des.push_back(
                D3D11_INPUT_ELEMENT_DESC{
                    Map<VertexType::Position2D>::semantic,0,Map<VertexType::Position2D>::dxgiFormat,0,offset,
                    D3D11_INPUT_PER_VERTEX_DATA,0

                });
            offset  = Map<VertexType::Position2D>::offset;
        }
        default:
            break;
        }
    }
 

Ответ №1:

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

Альтернатива: Ну, технически, в вашем случае, самое близкое, что вы могли бы сделать для достижения чего-то подобного, — это обернуть утомительную часть внутри макроса для удобства:

 // ...
for (const auto amp;i : v)
{
    /* This macro wraps around the checking of i's value and also assigns an alias for Map that
       can be used repeatedly */
    #define ITER_VERTEX_TYPE(x, body) if (i == VertexType::x) { 
                                          using Map = Map<VertexType::x>; 
                                          body; 
                                      }

    // Now you can use it like this:
    ITER_VERTEX_TYPE(Position2D, {
        // 'Map' is a type alias defined by the macro that refers to 'Map<VertexType::Position2D>'
        des.push_back(D3D11_INPUT_ELEMENT_DESC{ Map::semantic, 0, Map::dxgiFormat, 0, offset,
                      D3D11_INPUT_PER_VERTEX_DATA, 0 });
        offset  = Map::offset;
    })

    // Now do the same for the other enum values of 'VertexType' ...

    // Remove the macro since we don't need it anymore
    #undef ITER_VERTEX_TYPE
}
// ...
 

Комментарии:

1. Это кажется хорошим решением , я попробую ,спасибо!

Ответ №2:

как получить доступ к другому объекту шаблона через переменные вместо использования переключателя

Итак, если я правильно понимаю , у вас есть перечисление VertexType и структура Map , которая является шаблоном , и у вас есть переменная типа VertexType , и вы хотите «подключить» эту переменную в качестве аргумента шаблона, а не использовать оператор switch.

У меня есть плохие новости: это невозможно в C .

Шаблоны C — это не то же самое животное, что дженерики в C# или Java, где, как вы, возможно, знаете, вы можете делать подобные вещи. Типы переменных должны быть известны во время компиляции; вы не можете сделать ничего, что изменило бы тип переменной во время выполнения.

Ответ №3:

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

На вашем месте я бы вообще ничего здесь не создавал, вместо этого я бы специализировался и наследовал. Таким образом, у вас может быть действительно аккуратный код с почти теми же преимуществами шаблонов, если вы создаете с оптимизацией-O3 или в режиме выпуска на MSVC.

Кроме того, вектор в вашем коде выше пуст, поэтому ваш цикл auto for ничего не сделает. Может быть, ты хочешь std::array<Map, SIZE_HERE> вместо этого.

Подобный этому:

 enum class VertexType
{
    POSITION2D,
    POSITION3D
};

//Not templated!
struct Map {};

struct Map_2D : public Map {
    const VertexType vt = VertexType::POSITION2D;
    //other members here
};

struct Map_3D : public Map {
    const VertexType vt = VertexType::POSITION3D;
    //Other members here
};

int main()
{
    std::vector<Map> v;

    Map_2D map2d;
    Map_3D map3d;

   v.push_back(map2d);
   v.push_back(map3d);
}