【问题标题】:Is std::decay redundant in std::is_convertible?std::decay 在 std::is_convertible 中是多余的吗?
【发布时间】:2021-01-13 10:54:56
【问题描述】:

我写了这样的代码:

template <class T>
class A {
  template <class U, class = 
class std::enable_if_t<std::is_convertible_v<std::decay_t<U>, std::decay_t<T>>>>
      void f(U&& val) {}
    };

我希望我的班级用户只能使用可转换为 T 的类型调用 f

std::decay 是多余的吗?如果我删除它,我可能会错过一些特殊情况?

【问题讨论】:

  • 这取决于;你到底想问什么?也就是说,你试图阻止人们通过什么代码?
  • @NicolBolas,我正在编辑帖子。
  • "我希望我班级的用户只能使用可转换为 T 的类型调用 f​​。" 我可以从您的代码中猜到这一点。我想确切地了解你的意思。你的意思是你想让f 能够做T t = val; 或类似的东西?您希望用户能够将数组或函数类型作为T 传递吗?
  • @NicolBolas,你能解释一下最后一句话的意思吗?

标签: c++ c++17 enable-if perfect-forwarding


【解决方案1】:

我认为您的问题更具哲学性,例如:在 C++ 的类型世界中,是否存在 T 和 U 的任何情况,在以下类中调用 f() 和 g() 之间存在明显差异:

template <class T>
struct A {
 
    template <
        class U, 
        enable_if_t<is_convertible_v<decay_t<U>, decay_t<T>>>* = nullptr
    >
    void f(U&& val) {}

    template <
        class U, 
        enable_if_t<is_convertible_v<U, T>>* = nullptr
    >
    void g(U&& val) {}
};

decay_t 的实际作用是什么?

  • 删除顶级 const/volatile 限定符
  • 删除顶级引用限定符
  • 数组->指针转换
  • 函数->函数指针转换

可能值得注意的是:decay_t 是根据传递给函数时函数参数类型发生的情况建模的。 因此,decay_t&lt;U&gt; 应该始终等价于 U(前提是模板推导机制不被显式模板参数颠覆。)

因此,我们只需要关注decay_t&lt;T&gt; 并思考这些案例:

  • 可以将 T 转换为 T& 吗? (不)
  • 函数指针可以转换为函数类型吗? (不)
  • 可以将 T* 转换为 T[] 吗? (不)
  • 可以将 T 转换为 const T 吗? (是)

所以我们应该能够构建案例来证明这些观察结果:

// T is ARRAY type
A<int[]> a1; 
int ary[] = {1,2,3};
a1.f(ary);  // OK
a1.g(ary);  // ERROR (U decays to T*)

// T is REFERENCE type
A<int&> a2;
a2.f(123);  // OK
a2.g(123);  // ERROR (U decays to int)

// T is FUNCTION type
A<void()> a3;
a3.f(foo);  // OK
a3.g(foo);  // ERROR (U decays to void(*)()

// T is const type
A<const int> a4;
a4.f(123);  // OK
a4.g(123);  // OK

所以是的,在某些情况下衰减的值无法返回,并且由于 U 是隐式衰减的,当 T 没有衰减时,在某些情况下您可能会遇到一些错误。

您可以安全地从 U 中删除 decay_t,但在 T 上会有所不同。

现场观看 https://godbolt.org/z/P5P64Y

【讨论】:

    猜你喜欢
    • 2014-03-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-19
    • 2016-04-09
    • 1970-01-01
    • 2017-12-11
    • 2022-09-23
    相关资源
    最近更新 更多