Доступ к статическому члену вложенного класса шаблона

У меня есть шаблонный класс (Outer), и я хочу создать вложенный шаблонный класс на основе перечисления класса. Этот внутренний класс имеет статические переменные, поэтому, чтобы они были доступны, их необходимо определить вне класса.

template <class T>
class Outer
{
private:
  enum InnerType {foo, bar /* etc */};
  
  template <InnerType U>
  class Inner
  {
  public:
    static int x;
  };

public:
  // access Inner<>::x
  void print() { std::cout << Inner<foo>::x << std::endl; }
};

// somehow define Inner<>::x

Я пробовал несколько разных вариантов синтаксиса в принятом ответе здесь, но, похоже, у меня не получается. Он компилируется, если я заменяю перечисление классом для каждого значения, но перечисление гораздо более явное. Можно ли здесь использовать перечисление?

В зависимости от того, на какую версию стандарта C++ вы ориентируетесь, вы можете определить ее встроенным образом: inline static int x = 0; Обратите внимание, что это функция C++17.

Some programmer dude 12.08.2024 18:00

Это нарушит инкапсуляцию и добавит геттер к вашему внешнему классу. Код, использующийOuter, НИКОГДА не должен зависеть от внутреннего устройства класса. И это еще более справедливо в отношении глобальных переменных (которые являются статическими членами). Также в C++ используйте enum class now и распечатайте (функции вывода также никогда не должны быть частью класса). Не расстраивайтесь из-за моих комментариев, я просто вижу здесь некоторые недостатки дизайна :)

Pepijn Kramer 12.08.2024 18:00

Вы также можете использовать inline constexpr int x{42}; (из заголовочного файла, в противном случае используйте static constexpr. Это вообще не сделает ее глобальной переменной (а будет константой времени компиляции), {42} также присвоит значение (время компиляции).

Pepijn Kramer 12.08.2024 18:02

Как я уже говорил, используйте inline с C++17.

user12002570 12.08.2024 18:02

Я бы выбрал static inline int x = 42;Демо

Jarod42 12.08.2024 18:02

Кажется, я не могу заставить его работать. Опубликуйте дословное сообщение об ошибке, чтобы его можно было проиндексировать поисковыми системами, и ваш вопрос станет полезным для других пользователей, которые сталкиваются с подобными ошибками.

3CxEZiVlQ 12.08.2024 18:10

Думаю, вопрос достаточно ясен, чтобы на него можно было ответить. ОП хочет знать, как определить статический член вне шаблона класса.

Alex 12.08.2024 18:12

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

Mark Ransom 12.08.2024 18:12
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

поэтому их нужно будет определить вне класса

Это не обязательно так. В c++17 мы можем использовать inline для предоставления определения внутри шаблона класса, как показано ниже.

Если вы используете стандарт до C++17, см. первое решение. Обратите внимание на использование ключевого слова enum в версиях до C++17.

Итак, есть два способа решить эту проблему в зависимости от используемого вами стандарта С++, как показано ниже.

До C++17

Здесь мы даем определение вне класса:

//-------------------------vvvv---------------------------->note this enum keyword
template<class T> template<enum Outer<T>::InnerType I>  int Outer<T>::template Inner<I>::x =0;

Рабочая демо


С++17

Мы можем использовать inline, чтобы предоставить определение внутри класса.

template <class T>
class Outer
{
private:
  enum InnerType {foo, bar /* etc */};
  
  template <InnerType U>
  class Inner
  {
  public:
//--vvvvvv-------------------->with c++17
    inline static int x = 0;
  };
//other code as before
};

отклонено clang Демо

Jarod42 12.08.2024 18:09

@ Jarod42 Jarod42 Да, я это видел, сообщаю об ошибке с лязгом. Размещу ссылку здесь.

user12002570 12.08.2024 18:14

Другие вопросы по теме

Похожие вопросы