#c
Вопрос:
Название может не очень ясно выражать мой смысл
- Создал шаблон карты классов, типом которого является перечисление VertexType, и специализирую их
- существует векторный контейнер типа VertexType
- доступ к другому объекту карты через элемент в векторе
- Вопрос: как получить доступ к другому объекту шаблона через переменные вместо переключателя 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);
}