对或元组值的名称别名引用
Name alias references for pair or tuple values
在重构一些代码时,我遇到了 'problem' 当 returning 具有 2 个值的结构时。现在这些真的应该以记录的效果命名。后来我想使用 tie
所以我将结构更改为继承自 std::pair
并仅设置引用。现在这实际上工作正常,但你会注意到现在我的结构的大小为 24,而不是与这对结构相比只有 8。
#include <tuple>
struct Transaction : public std::pair<int, int> {
using pair::pair;
int& deducted = first;
int& transfered = second;
};
//static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));//commenting in this line will fail compilation
Transaction makeTheTransaction();
void test(int& deduct, int& transfer) {
std::tie(deduct, transfer) = makeTheTransaction();
}
可能显而易见的方法是更改为成员函数,但是对于这种情况来说,这也太多了 'boilerplate'(这样以后就更容易不使用 tie
)。一个直接的 memcpy 是例如。元组是直截了当的 UB。直接结构化绑定也不可行,因为变量已在使用中。
我的问题是什么是忽略可重用部分的更好或最小代码解决方案(并且考虑到大小不应超过 2 个整数的大小)?
更新:对于这种情况,我最终只是做了一个简单的结构并临时保存 return 。对于来到这里的其他用户,有一个 boost 库提案似乎能够将任何结构转换为元组:https://github.com/apolukhin/magic_get/
我会选择:
struct Transaction
{
int deducted;
int transfered;
};
用法类似于:
Transaction makeTheTransaction() { return {4, 2}; }
int main()
{
auto [deduct, transfer] = makeTheTransaction();
std::cout << deduct << transfer << std::endl;
}
看来你把问题复杂化了。如果需要使用std::tie
,直接使用即可。无需更改您的结构:
struct Transaction
{
int deducted;
int transferred;
};
// later...
auto t = std::tie(transaction.deducted, transaction.transferred);
如果这是您经常使用的模式,那么您可以将其包装在一个小辅助方法中:
struct Transaction
{
int deducted;
int transferred;
auto to_tuple() const
{
return std::tie(deducted, transferred);
}
};
您也可以使用它一次分配给多个变量,但我强烈反对这样做。它容易出错并导致代码脆弱。 (例如,如果在下面的示例中颠倒 deduct
和 transfer
的顺序,就会出现错误,但编译器不会给出警告或错误。)
void test(int& deduct, int& transfer)
{
std::tie(deduct, transfer) = makeTheTransaction().to_tuple();
}
编辑:再三考虑...
如果这里的目标只是简单地将结构分解为变量,您可以直接这样做并避免使用对或元组:
struct Transaction
{
int deducted;
int transferred;
void decompose(int* deducted_, int* transferred_)
{
*deducted_ = deducted;
*transferred_ = transferred;
}
};
void test(int& deduct, int& transfer)
{
makeTheTransaction().decompose(&deduct, &transfer);
}
这仍然很脆弱,但至少现在当您编写对 decompose
方法的调用时,您将获得智能感知,这将使模式不太容易出错。
添加转换函数有效:
#include <tuple>
struct Transaction {
std::pair<int, int> data_;
operator std::tuple<int &, int &> () {
return std::tie(data_.first, data_.second);
}
};
static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));
Transaction makeTheTransaction() {
return Transaction();
}
void test(int& deduct, int& transfer) {
std::tie(deduct, transfer) = makeTheTransaction();
}
我不认为这会导致与 std::tie 一起使用时出现任何生命周期问题。
此 Transaction
不适用于具有两个标识符的结构化绑定。但是你可以通过专门化 std::get
和 std::tuple_size
来让它支持 "tuple-like" 绑定。
在重构一些代码时,我遇到了 'problem' 当 returning 具有 2 个值的结构时。现在这些真的应该以记录的效果命名。后来我想使用 tie
所以我将结构更改为继承自 std::pair
并仅设置引用。现在这实际上工作正常,但你会注意到现在我的结构的大小为 24,而不是与这对结构相比只有 8。
#include <tuple>
struct Transaction : public std::pair<int, int> {
using pair::pair;
int& deducted = first;
int& transfered = second;
};
//static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));//commenting in this line will fail compilation
Transaction makeTheTransaction();
void test(int& deduct, int& transfer) {
std::tie(deduct, transfer) = makeTheTransaction();
}
可能显而易见的方法是更改为成员函数,但是对于这种情况来说,这也太多了 'boilerplate'(这样以后就更容易不使用 tie
)。一个直接的 memcpy 是例如。元组是直截了当的 UB。直接结构化绑定也不可行,因为变量已在使用中。
我的问题是什么是忽略可重用部分的更好或最小代码解决方案(并且考虑到大小不应超过 2 个整数的大小)?
更新:对于这种情况,我最终只是做了一个简单的结构并临时保存 return 。对于来到这里的其他用户,有一个 boost 库提案似乎能够将任何结构转换为元组:https://github.com/apolukhin/magic_get/
我会选择:
struct Transaction
{
int deducted;
int transfered;
};
用法类似于:
Transaction makeTheTransaction() { return {4, 2}; }
int main()
{
auto [deduct, transfer] = makeTheTransaction();
std::cout << deduct << transfer << std::endl;
}
看来你把问题复杂化了。如果需要使用std::tie
,直接使用即可。无需更改您的结构:
struct Transaction
{
int deducted;
int transferred;
};
// later...
auto t = std::tie(transaction.deducted, transaction.transferred);
如果这是您经常使用的模式,那么您可以将其包装在一个小辅助方法中:
struct Transaction
{
int deducted;
int transferred;
auto to_tuple() const
{
return std::tie(deducted, transferred);
}
};
您也可以使用它一次分配给多个变量,但我强烈反对这样做。它容易出错并导致代码脆弱。 (例如,如果在下面的示例中颠倒 deduct
和 transfer
的顺序,就会出现错误,但编译器不会给出警告或错误。)
void test(int& deduct, int& transfer)
{
std::tie(deduct, transfer) = makeTheTransaction().to_tuple();
}
编辑:再三考虑...
如果这里的目标只是简单地将结构分解为变量,您可以直接这样做并避免使用对或元组:
struct Transaction
{
int deducted;
int transferred;
void decompose(int* deducted_, int* transferred_)
{
*deducted_ = deducted;
*transferred_ = transferred;
}
};
void test(int& deduct, int& transfer)
{
makeTheTransaction().decompose(&deduct, &transfer);
}
这仍然很脆弱,但至少现在当您编写对 decompose
方法的调用时,您将获得智能感知,这将使模式不太容易出错。
添加转换函数有效:
#include <tuple>
struct Transaction {
std::pair<int, int> data_;
operator std::tuple<int &, int &> () {
return std::tie(data_.first, data_.second);
}
};
static_assert(sizeof(Transaction) == sizeof(std::pair<int, int>));
Transaction makeTheTransaction() {
return Transaction();
}
void test(int& deduct, int& transfer) {
std::tie(deduct, transfer) = makeTheTransaction();
}
我不认为这会导致与 std::tie 一起使用时出现任何生命周期问题。
此 Transaction
不适用于具有两个标识符的结构化绑定。但是你可以通过专门化 std::get
和 std::tuple_size
来让它支持 "tuple-like" 绑定。