#c #templates #struct #static #constants
#c #шаблоны #структура #статический #константы
Вопрос:
Чего я пытаюсь достичь, так это использовать структуру в качестве параметра шаблона для другой структуры без создания экземпляра, чтобы все это происходило во время компиляции. Например:
template<int v>
struct Container {
static const int value = v;
};
template<Container a, Container b>
struct BiggerContainer {
static const int value = a.v > b.v ? a.v : b.v;
};
int main() {
std::cout << BiggerContainer<Container<42>, Container<42>>::value << std::endl;
return 0;
}
Ошибка, которую я получаю с этим кодом, заключается в следующем:
./code.cpp: In function 'int main()':
./code.cpp:44:61: error: type/value mismatch at argument 1 in template parameter list for 'template<Container<...auto...> a, Container<...auto...> b> struct BiggerContainer'
44 | std::cout << BiggerContainer<Container<42>, Container<42>>::value << std::endl;
| ^~
./code.cpp:44:61: note: expected a constant of type 'Container<...auto...>', got 'Container<42>'
./code.cpp:44:61: error: type/value mismatch at argument 2 in template parameter list for 'template<Container<...auto...> a, Container<...auto...> b> struct BiggerContainer'
./code.cpp:44:61: note: expected a constant of type 'Container<...auto...>', got 'Container<42>'
Что я здесь не так понимаю? Что именно означает эта ошибка, что я могу изменить, чтобы получить то, что я пытаюсь?
Спасибо!
Ответ №1:
Возможно, у вас:
template <int v>
struct Container {
static const int value = v;
};
// template <int v> using Container = std::integral_constant<int, v>;
template <typename lhs, typename rhs>
struct Max
{
static const int value = lhs::value > rhs::value ? lhs::value : rhs::value;
};
int main() {
std::cout << Max<Container<42>, Container<42>>::value << std::endl;
}
Ответ №2:
В C 17 вы не можете использовать класс или структуру в качестве параметра шаблона, отличного от типа. Нетиповые параметры должны быть целыми числами, указателями, перечислениями или ссылками. Это меняется в C 20.
В частности, следующее объявление параметризует BiggerContainer
значения структур, что невозможно.
template<Container a, Container b>
struct BiggerContainer
Есть несколько других проблем с кодом, но это основная проблема, из-за которой вам придется переделывать вещи.
Ответ №3:
Проблема в том, что в аргументах вашего шаблона для BiggerContainer
вам нужно указать аргументы шаблона для Container
( template<Container, Container>
у него нет аргументов шаблона для Container
).
Одной из альтернатив является использование шаблонной функции, например:
template<int v1, int v2>
int BiggerContainer(Container<v1> a, Container<v2> b)
{
return a.value > b.value ? a.value : b.value;
}
Затем вызываем его как:
BiggerContainer(Container<42>(), Container<42>()); // No need to add '::value'
ПРИМЕЧАНИЕ: необходимо вызывать конструктор, Container<val>()
а не просто тип Container<val>
. (Потому что мы передаем значение, а не тип)
Проблема с этим решением заключается в том, что оно возвращает int (тип значения), а не a Container
, но для некоторых целей это может быть нормально.