Как использовать вложенные статические шаблонные структуры в c 17

#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 , но для некоторых целей это может быть нормально.