Как правильно написать и применить концепцию C++20 / SFINAE / для выбора функции через определение структуры?C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Как правильно написать и применить концепцию C++20 / SFINAE / для выбора функции через определение структуры?

Сообщение Anonymous »

Я пытаюсь создать сериализуемую оболочку переменных через RapidJSON. Я хочу предоставить определяемые пользователем функции преобразования или функции преобразования литералов по умолчанию, когда UserType удовлетворяет концепции или нет. Я хочу написать кросс-скомпилированное решение (MSVS и MinGW).
SerializableVariable videoMode = { "videoMode", sf::VideoMode(1920, 1080)};
SerializableVariable style = { "style", sf::Uint32(sf::Style::Fullscreen) }

rapidjson::Value initValue = ...;
Serializable* var = ...; 
var->ToJson();
var->FromJson(initValue);

Я написал эту обертку именно для этой цели:

class Serializable
{
public:
Serializable() = default;

Serializable(const char* name)
: name { name }
{ }

rapidjson::Document ToJson()
{
rapidjson::Document document;
StoreNewDocumentAllocator(document.GetAllocator());
document.SetObject().AddMember(rapidjson::StringRef(GetName()), static_cast(*this), *documentAllocator);

return document;
}

virtual operator rapidjson::Value() = 0;

inline operator std::string()
{
rapidjson::StringBuffer buffer;
rapidjson::PrettyWriter writer(buffer);
writer.SetIndent(' ', 2);
writer.SetFormatOptions(rapidjson::kFormatSingleLineArray);

ToJson().Accept(writer);

return buffer.GetString();
}

friend std::ostream& operator value.Get();
videoMode.width = hit->value.Get();
}
}

inline rapidjson::Value toJson(const sf::VideoMode& videoMode)
{
rapidjson::Value value(rapidjson::kObjectType);

value["Width"] = videoMode.width;
value["Height"] = videoMode.height;

return value;
}
}

Проблема 1. Выбор пользовательского преобразователя не удался, поскольку сначала не удалось выполнить версию для литералов (не определена Get в выражении Initializer.template Get()) и эта концепция не помогает в выражении if-constexpr.
Проблема 2. Попытка определить структуру с разрешенным преобразователем UserType не удалась из-за внутренней ошибки шаблона RapidJSON:
error: 'Get' is not a member of 'rapidjson::internal::TypeHelper'
1747 | T Get() const { return internal::TypeHelper::Get(*this); }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~

Пожалуйста, помогите мне понять, что я делаю не так.
Функции для тестирования:
template
inline auto attempt()
{
rapidjson::Value json;
UserType val;

// All fine with this when do in directly without compile-time selecting
// Converters::fromJson(val, json);
// Converters::toJson(val);
// UserJsonConversions::fromJson(val, json);
// UserJsonConversions::toJson(val);

// Compiles for sf::Uint32, but CLion says that it's error
// But for sf::VideoMode got error
Converters::Distinct::fromJson(val, json);
Converters::Distinct::toJson(val);

// Decide on compile-time what is need to be called works for literal types
if constexpr (Converters::HasFromJsonCast)
{
Converters::fromJson(val, json); // Error for sf::VideoMode
/*
error: 'Get' is not a member of 'rapidjson::internal::TypeHelper'
1747 | T Get() const { return internal::TypeHelper::Get(*this); }
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
*/
} else
{
UserJsonConversions::fromJson(val, json);
}

if constexpr (Converters::HasToJsonCast)
{
return Converters::toJson(val);
} else
{
return UserJsonConversions::toJson(val);
}
}

inline void f()
{
attempt();
// attempt();
}

Я также попробовал использовать другой способ проверки существующей функции-члена шаблона в классе шаблона. Может я делаю неправильно и это правильно?
template
class CheckGetExistsIn {
typedef char yes[1];
typedef char no[2];

template
static yes& test(decltype(&LibType::template Get));

template
static no& test(...);

public:
template
static const bool forUserType = sizeof(test(0)) == sizeof(yes);
};

template
concept HasFromJsonCast = CheckGetExistsIn::forUserType;


Подробнее здесь: https://stackoverflow.com/questions/783 ... ction-sele
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»