在只读(即 const)访问器上执行结构化绑定的最佳实践是什么?
What is the best practice for performing structured bindings on read-only (i.e. const) accessors?
考虑以下 class foo
:
class foo {
private:
int x = 0;
int y = 0;
public:
template <std::size_t I>
int const& get() const
{
if constexpr (I == 0) {
return x;
}
else return y;
}
};
我想为 foo
实现结构化绑定,所以我添加了以下内容:
namespace std {
template <>
struct tuple_size<foo> : std::integral_constant<std::size_t, 2u> {};
template <std::size_t I>
struct tuple_element<I, foo> {
using type = int;
};
}
现在,如果用户要执行结构绑定,he/she 必须显式添加 const 限定符:
int main() {
foo f;
auto [a, b] = f; // Won't compile
auto& [x, y] = f; // Won't compile
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
return 0;
}
(因为我们无法将 int&
绑定到 int const&
)
或者,我可以将 tuple_element
typedef 设为 const int
。现在所有四个语句都编译:
namespace std {
template <>
struct tuple_size<foo> : std::integral_constant<std::size_t, 2u> {};
template <std::size_t I>
struct tuple_element<I, foo> {
using type = const int; // <=== const added here
};
}
int main() {
foo f;
auto [a, b] = f; // Compiles
auto& [x, y] = f; // Compiles
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
return 0;
}
现在请注意,即使它们的声明中没有 const 限定符,a
、b
、x
和 y
都是 int const
.这可能会让用户感到困惑。
所以我的问题是:以上哪一项被认为是更好的做法?
So my question is: which one of the above is considered a better practice?
更喜欢第二种方法来尝试模仿内置和标准的情况:
class foo {
public:
const int x = 0;
const int y = 0;
};
int main() {
foo f;
auto [a, b] = f; // Compiles
auto& [x, y] = f; // Compiles
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
}
std::tuple<float&,char&&,int> tpl(x,std::move(y),z);
const auto& [a,b,c] = tpl;
// a names a structured binding that refers to x; decltype(a) is float&
// b names a structured binding that refers to y; decltype(b) is char&&
// c names a structured binding that refers to the 3rd element of tpl; decltype(c) is const int
考虑以下 class foo
:
class foo {
private:
int x = 0;
int y = 0;
public:
template <std::size_t I>
int const& get() const
{
if constexpr (I == 0) {
return x;
}
else return y;
}
};
我想为 foo
实现结构化绑定,所以我添加了以下内容:
namespace std {
template <>
struct tuple_size<foo> : std::integral_constant<std::size_t, 2u> {};
template <std::size_t I>
struct tuple_element<I, foo> {
using type = int;
};
}
现在,如果用户要执行结构绑定,he/she 必须显式添加 const 限定符:
int main() {
foo f;
auto [a, b] = f; // Won't compile
auto& [x, y] = f; // Won't compile
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
return 0;
}
(因为我们无法将 int&
绑定到 int const&
)
或者,我可以将 tuple_element
typedef 设为 const int
。现在所有四个语句都编译:
namespace std {
template <>
struct tuple_size<foo> : std::integral_constant<std::size_t, 2u> {};
template <std::size_t I>
struct tuple_element<I, foo> {
using type = const int; // <=== const added here
};
}
int main() {
foo f;
auto [a, b] = f; // Compiles
auto& [x, y] = f; // Compiles
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
return 0;
}
现在请注意,即使它们的声明中没有 const 限定符,a
、b
、x
和 y
都是 int const
.这可能会让用户感到困惑。
所以我的问题是:以上哪一项被认为是更好的做法?
So my question is: which one of the above is considered a better practice?
更喜欢第二种方法来尝试模仿内置和标准的情况:
class foo {
public:
const int x = 0;
const int y = 0;
};
int main() {
foo f;
auto [a, b] = f; // Compiles
auto& [x, y] = f; // Compiles
const auto [c_a, c_b] = f; // Compiles
const auto& [c_x, c_y] = f; // Compiles
}
std::tuple<float&,char&&,int> tpl(x,std::move(y),z); const auto& [a,b,c] = tpl; // a names a structured binding that refers to x; decltype(a) is float& // b names a structured binding that refers to y; decltype(b) is char&& // c names a structured binding that refers to the 3rd element of tpl; decltype(c) is const int