【问题标题】:When do we need Tag Dispatching in Template Metaprogramming?我们什么时候需要模板元编程中的标签调度?
【发布时间】:2021-12-04 01:11:23
【问题描述】:

我是模板元编程的新手,我正在观看 Jody Hagins 的 type traits talk part II。我想复制一个函数重载解析示例,以使用以下方法检测给定类型是否为常量:

namespace detail {
template <typename T>
std::true_type is_const(T const);

template <typename T>
std::false_type is_const(T);
}  // namespace detail

template <typename T>
using is_constant = decltype(detail::is_const(std::declval<T>()));

static_assert(is_constant<int const>::value);

上述静态断言会产生一个编译器错误,指出对 is_const 的调用不明确。如果我使用TypeTag 将T 包含在我的模板声明中,事情会按预期工作:

template <typename T>
struct TypeTag {};

namespace detail {
template <typename T>
std::true_type is_const(TypeTag<T const>);

template <typename T>
std::false_type is_const(TypeTag<T>);
}  // namespace detail

template <typename T>
using is_constant = decltype(detail::is_const(std::declval<TypeTag<T>>()));

static_assert(is_constant<int const>::value);

我很困惑为什么没有TypeTag 封装的第一个声明是模棱两可的。我的猜测是它与 declval 返回类型为 T 的 cv-qualified 类型有关,但我不明白第二种情况是如何工作的。

是不是因为在第一种情况下declval&lt;int const&gt; 有返回类型 int 但在第二种情况下declval&lt;TypeTag&lt;int const&gt;&gt; 有返回类型TypeTag&lt;int const&gt; 所以编译器选择第一个模板特化 T替换为 int 并且模板调用如下所示:

<>
std::true_type is_const<TypeTag<int const>>;

如果我的猜测是正确的,是否有一种通用的做法是使用带有TypeTag(空结构模板)的标签调度来防范cv-qualified 类型?

【问题讨论】:

  • is_const(T) 和 is_const(T const) 相同,因此有歧义。

标签: c++ templates metaprogramming template-meta-programming


【解决方案1】:

第一个示例不起作用的原因是顶级函数参数中的const 被忽略,因此is_const(T) 和is_const(T const) 是相同的函数签名。如果const 不是顶级的,则函数签名不同,例如is_const(T*) 和 is_const(T* const) 是不同的。

在您的第二个示例中,is_const(TypeTag&lt;T&gt;) 和 is_const(TypeTag&lt;T const&gt;) 不同,因为 TypeTag&lt;T&gt; 和 TypeTag&lt;T const&gt; 是不相关的类型。

但是,我认为您对 TypeTag 的使用不符合“标签调度”的条件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-08
    相关资源
    最近更新 更多