【发布时间】:2016-12-23 12:04:20
【问题描述】:
在对参数包进行递归时,如果可以选择,我应该更喜欢通过继承还是通过成员字段(组合)进行递归?这是一刀切吗?有哪些取舍?
我想知道的一件事是,例如,基于组合的表单是否通常被认为具有更好的编译速度、内存使用或错误报告。
为了说明,以下是受 Jonathan Wakely 的回答 here 启发的短路 or_(析取)示例。
基于继承:
#include <type_traits>
// disjunction
template<typename... Conds>
struct or_ : std::false_type {};
template<typename Cond, typename... Conds>
struct or_<Cond, Conds...>
: std::conditional<Cond::value, std::true_type, or_<Conds...>>::type
{};
static_assert(or_<std::true_type, std::true_type, std::true_type>::value,"");
static_assert(or_<std::false_type, std::false_type, std::true_type>::value,"");
static_assert(or_<std::false_type, std::false_type, std::false_type>::value == false,"");
我了解此版本具有or_<Ts...> 将从std::integral_constant 继承的功能。为了我的问题,请假设我不关心 or_ 是否继承自 integral_constant。
基于作曲:
template<typename... Conds>
struct or_ {
static constexpr bool value = false;
};
template<typename Cond, typename... Conds>
struct or_<Cond, Conds...> {
static constexpr bool value = std::conditional<Cond::value, std::true_type, or_<Conds...>>::type::value;
};
这种形式在我看来直觉上更好,因为值总是位于类型本身,而不是某些超类中,但我不确定这是否通常被认为是可取的。
附:我知道在 C++17 中我经常可以使用折叠表达式。但我的目标是与 C++11 兼容。
【问题讨论】:
-
这是个人喜好问题。最终结果是相同的,并且两种方法都没有任何特别的优势。
-
这主要是基于意见的。您立即忽略的继承具有重要的好处(简化标签调度,加上
integral_constant提供的几个实用程序)。我想有人可能会争辩说,有人可能会忘记第二种形式的static,尤其是如果你写的是const而不是constexpr,这可能会导致在依赖上下文中令人费解的替换失败。 -
在 C++11 中,人们仍然可以使用以某种方式预期折叠表达式的技巧作为第三种方法。在 C++14 中,您可以使用模板变量来实现,这是另一种不同的方法。为什么你只对问题中的两个感兴趣?
-
@skypjack:你能指出我提到的另外两种方法的例子吗?我不确定我是否明白你的意思。
-
@RossBencina Here 就是其中之一。