提问人:Capy Maths 提问时间:10/2/2023 更新时间:10/2/2023 访问量:132
增强了 C++ 中的“自动”[已关闭]
Strengthened 'auto' in C++ [closed]
问:
曾几何时,我意识到我希望能够在不复制代码的情况下编写这样的代码:
template<std::size_t N>
std::ostream& operator<< (std::ostream& o, const vector_type<N>& vector)
{
if constexpr (passed_by_value<typename vector_type<N>::value_type>)
{
for (const auto val : vector)
{
o << val << ' ';
}
}
else
{
for (const auto& val : vector)
{
o << val << ' ';
}
}
return o;
}
示例中的重复代码是(或者可能是整个循环)。o << val << ' '
当然,我知道为了避免代码重复,我们可以引入一个包含代码的函数。然而,这并不是我真正想要的解决方案。我希望它简单明了。
我在示例中使用的原因是我希望我的模板函数能够同时处理值类型的容器和 ref 类型的容器。所以在一个块中我这样做,而在另一个块中 - .if constexpr
const auto
const auto&
如果我们能实现一个行为如下的类型,那就太好了:super_type
int passed_by_value = 100;
std::string passed_by_ref = "abcdefghijklmnop";
super_auto value = passed_by_value; // works like auto
super_auto value = passed_by_ref; // works like auto&
const super_auto value = passed_by_value; // works like const auto
const super_auto value = passed_by_ref; // works like const auto&
因此,我们可以编写以下代码,这些代码既适用于 value- 类型,也适用于 ref 类型:
for (const super_auto val : vector)
{
o << val << ' ';
}
这看起来与转发 ref 相似,但它并不总是 ref,因此转发 ref 似乎对我们没有帮助。
那么问题来了,我们如何实现我所描述的逻辑呢?我在哪里弄错了吗?或者 std lib 中是否有任何解决方案?
答:
4赞
Drew Dormann
10/2/2023
#1
std::conditional
可以生成基于编译时布尔值的类型。
template<std::size_t N>
std::ostream& operator<< (std::ostream& o, const vector_type<N>& vector)
{
using value_type = typename vector_type<N>::value_type;
using super_auto = std::conditional_t<
passed_by_value<value_type>,
value_type,
value_type& >;
for (const super_auto val : vector)
{
o << val << ' ';
}
return o;
}
也就是说,这种复杂性不太可能以任何方式使您受益。
下面的代码清晰有效地执行相同的工作。
template<std::size_t N>
std::ostream& operator<< (std::ostream& o, const vector_type<N>& vector)
{
for (const auto& val : vector)
{
o << val << ' ';
}
return o;
}
评论
0赞
Ted Lyngmo
10/2/2023
由于您制作了别名,因此可以简化为 - 并且可能会使其更通用一些。passed_by_value<typename vector_type<N>::value_type>
passed_by_value<value_type>
using value_type = std::iterator_traits<decltype(std::begin(vector))>::value_type;
1赞
Drew Dormann
10/2/2023
@TedLyngmo好渔获!感谢分享。
0赞
Capy Maths
10/2/2023
感谢您的建议。这看起来不错,但我确实想要一些更隐含的东西。使用需要指定类型。然而,对我来说,更多的是通过隐含的推导来省略类型规范。因此,只有当您提供实现所描述的推导的方法而没有任何额外的本地 typedef 或其他东西时,我才会感到满意。可能是一些结构或类,我会在不了解其后台的类型操作的情况下包含和使用。std::conditional
auto
super_auto
1赞
Ted Lyngmo
10/3/2023
@CapyMaths 如果使用 那么,即使对于不同类型的普通 C 数组也会被推导出来。由于你想根据你的类型特征使用不同的类型,我认为你不会比使用德鲁在这个答案中所示更简单。using value_type = std::iterator_traits<decltype(std::begin(vector))>::value_type
value_type
std::conditional
评论
if
else
for (const auto& val : vector)
很可能是所有类型的最佳方法。