0

在我目前编写的一段代码中,我使用了类推导指南。您可以在下面找到精简为一个简单(但无意义的示例)的代码摘录:我有一个 class User,它从构造函数的第一个参数派生其第一个模板参数,第二个来自参数包的大小作为第二个参数提供:

#include <cstddef>
#include <type_traits>

/// First constructor parameter, which can be used in order to derive the boolean
template <int, bool switcher> struct P1 {};

/// Class which depends on the boolean flag (from first parameter) and the amount of elements provided.
template <bool switcher, size_t amountKids> struct User {
  template <int p1, int... pn> explicit constexpr User(P1<p1, switcher> &child,
      P1<pn, switcher>... parents) noexcept {}
};

/// Deduction guide
template <bool f, int p1, int... pn> User(P1<p1, f> &child, P1<pn, f> ...) ->User<f, sizeof...(pn) + 1>;

int main() {
  P1<1, true> child;
  User sa{child, P1<1, true>{}};
  User sa2{child, child, child};
}

这工作正常(编译)。但是,当我通过将参数包的类型替换为依赖于模板参数的类型来进行微小修改switcher时,推导失败:

#include <cstddef>
#include <type_traits>

/// First constructor parameter, which can be used in order to derive the boolean
template <int, bool switcher> struct P1 {};

/// In the real example, conditional_type holds a different type, depending on the #bool
template <bool, typename T> struct conditional_type { using type = T; };
template <bool switcher, typename T> using conditional_type_t = typename conditional_type<switcher, T>::type;

template <bool switcher, size_t amountKids> struct User {
  template <int p1, int... pn> explicit constexpr User(P1<p1, switcher> &child,
      conditional_type_t<switcher, P1<pn, switcher>>... parents) noexcept {}
};

template <bool f, int p1, int... pn> User(P1<p1, f> &child, conditional_type_t<f, P1<pn, f>>...) ->User<f, sizeof...(pn) + 1>;

int main() {
  conditional_type_t<true, P1<1, true>> child2;
  P1<1, true> child;
  static_assert(std::is_same_v<decltype(child), decltype(child2)>);

  User sa{child, P1<1, true>{}}; //< fails: 2 arguments provided, expecting one, can't derive amountKids
  User sa2{child, child, child}; //< fails: 
}

这是为什么?

代码的两种变体都可以在这里找到。

4

1 回答 1

2

您在第二个示例中的演绎指南等同于我们替换别名得到的内容:

template <bool f, int p1, int... pn>
User(P1<p1, f> &child, typename conditional_type<f, P1<pn, f>>::type ...)
    -> User<f, sizeof...(pn) + 1>;

在依赖类型的任何语法typename A::BA,类型A都是非推导上下文。由于pn只出现在非演绎的上下文中,因此永远无法演绎,因此永远无法使用演绎指南。

出于类似的原因,构造函数 ofUser永远不能与多个参数一起使用,即使模板参数User被显式指定。

于 2020-02-18T23:54:31.207 回答