У меня есть пользовательский тип (который я могу продлить):
struct Foo {
int a;
string b;
};
Как я могу создать экземпляр этого объекта, который можно присваивать std::tie
, т.е. std::tuple
ссылок?
Foo foo = ...;
int a;
string b;
std::tie(a, b) = foo;
Неудачные попытки:
Перегрузка оператора присваивания для tuple<int&,string&> = Foo
невозможна, поскольку оператор присваивания является одним из двоичных операторов, которые должны быть членами объекта левой стороны.
Поэтому я попытался решить эту проблему, выполнив подходящий оператор преобразования tuple. Не удалось выполнить следующие версии:
-
operator tuple<int,string>() const
-
operator tuple<const int&,const string&>() const
Они приводят к ошибке при присваивании, говоря, что "operator =
не перегружается для tuple<int&,string&> = Foo
". Я думаю, это связано с тем, что "преобразование в любой шаблон X + параметр шаблона X для оператора =" не работает вместе, только один из них сразу.
Несовершенная попытка:
Следовательно, я попытался реализовать оператор преобразования для точного типа привязки:
Назначение теперь работает, поскольку типы теперь (после преобразования) точно такие же, но это не будет работать для трех сценариев, которые я хотел бы поддержать:
- Если связь связана с переменными различных, но конвертируемых типов (т.е. измените
int a;
наlong long a;
на стороне клиента), она терпит неудачу, поскольку типы должны полностью соответствовать. Это противоречит обычному использованию назначения кортежа в кортеж ссылок, который позволяет конвертировать типы. (1) - Оператор преобразования должен вернуть связь, для которой должны быть заданы ссылки lvalue. Это не будет работать для временных значений или константных членов. (2)
- Если оператор преобразования не const, присваивание также не выполняется для
const Foo
с правой стороны. Чтобы реализовать const-версию преобразования, нам нужно снять константу членов объекта const. Это некрасиво и может быть злоупотреблено, что приводит к поведению undefined.
Я вижу только альтернативу в предоставлении моей собственной функции tie
function + class вместе с моими "связанными с привязкой" объектами, что заставляет меня дублировать функции std::tie
, которые мне не нравятся (не то, что я затрудниться с этим, но ему нехорошо это делать).
Я думаю, что в конце дня вывод заключается в том, что это один из недостатков реализации библиотеки только для кортежей. Они не такие волшебные, как нам бы хотелось.
EDIT:
Как оказалось, не существует реального решения всех вышеперечисленных проблем. Очень хороший ответ объяснил бы, почему это не разрешимо. В частности, я хотел бы, чтобы кто-то пролил свет на то, почему "неудачные попытки" не могут работать.
(1): ужасный взлом - это записать преобразование в качестве шаблона и преобразовать в запрошенные типы членов в операторе преобразования. Это ужасный взлом, потому что я не знаю, где хранить эти конвертированные элементы. В эта демонстрация Я использую статические переменные, но это не поточно-реентерабельный.
(2): Можно применить такой же взлом, как и в (1).