Re: ADL не ADL? Или как?
От: rg45 СССР  
Дата: 07.01.24 20:42
Оценка:
Здравствуйте, Marty, Вы писали:

M>Но это завязано на мои соглашения, что EnumType::invalidValue у меня всегда -1. С enum'ами, константы для которых могут зависеть от внешних спек, такое может не прокатить.


M>Наивная идея была сделать общий шаблон enum_deserialize_throwable, и генерить специализации для него. Но потом я вспомнил, что все сгенерённые функции попадают в то же пространство имён, что и сам enum, и это могут быть любые NS, и точно не то NS, в котором объявлен шаблон, который я хотел специализировать.


M>Как быть?


Честно признаюсь, не уверен, что полностью правильно понял все сценарии, но попробую предложить решение, а вдруг попаду. Ты можешь для каждого энума определить функцию получения дефолтного значения. Разумеется, эта функция должна быть определена в том же пространстве имен, что и сам энум — чтобы она могла быть найденной через ADL. Один лишь нюанс: для того, чтобы ADL правильно работал, у этой функции должен быть один формальный параметр, имеющий тип этого энума. При вызове этих функций можно будет передавать фактический параметр, сконструированный по дефолту. Еще один замечательный момент: эти функции, получающие дефолтный параметр могут быть как шаблонными, так и обычными, нешаблонными. Схематично так:

namespace ns1
{

enum E1
{
   invalidValue = -1,
   . . .
};

enum E2
{
   invalidValue = -1,
   . . .
};

enum E3
{
   None = -42,
   . . .
};

enum E4
{
   // No invalid value defined
   Good1 = 1,
   Good2 = 2,
   Good3 = 3
};

// Comon accessor
template <typename T>
constexpr T enum_default_value(T) { return T::invalidValue; }

// Special accessor for E3
constexpr E3 enum_default_value(E3) { return E3::None; }

// Special accessor for E4
constexpr E4 enum_default_value(E4) { return {}; } // Returns zero-initialized E4 object

} // namespace ns1

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

namespace ns2
{

void usage_example()
{
  enum_default_value(ns1::E1{}); // returns E1::invalidValue
  enum_default_value(ns1::E2{}); // returns E2::invalidValue
  enum_default_value(ns1::E3{}); // returns E3::None
  enum_default_value(ns1::E4{}); // returns E4{}
}

} // namespace ns2



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

namespace ns2
{

template <typename T>
constexpr enum_default_value() { return enum_default_value(T{}); }

void usage_example()
{
  enum_default_value<ns1::E1>(); // returns E1::invalidValue
  enum_default_value<ns1::E2>(); // returns E2::invalidValue
  enum_default_value<ns1::E3>(); // returns E3::None
  enum_default_value<ns1::E4>(); // returns E4{}
}
} // namespace ns2

Но это уже для совсем уж больших любителей синтаксического сахара, без этого вполне можно жить, я считаю. И надо понимать, что эта обертка не сможет находиться по ADL, в отличие от реальных аксессоров, определенных в пространствах имен энумов, и объявление этой обертки всегда должно быть видно в точке ее использования.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 08.01.2024 10:41 rg45 . Предыдущая версия . Еще …
Отредактировано 07.01.2024 21:08 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 21:01 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:57 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:55 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:55 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:54 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:46 rg45 . Предыдущая версия .
Отредактировано 07.01.2024 20:44 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.