【问题标题】:C++ base class non-type parameter specialization deduction with auto type specifier fails使用自动类型说明符的 C++ 基类非类型参数特化推导失败
【发布时间】:2020-04-29 06:13:35
【问题描述】:

这是问题的简化版本:

假设我有一个带有非类型参数的模板化基类,以及 2 个具有专业化的派生类。

template <int val>
struct Base {
};

struct Derived1 : public Base<1> {
};

struct Derived2 : public Base<2> {
};

template <int val>
int get(std::unique_ptr<Base<val>> ptr) {
    return val;
}

int main()
{
  // these work
  std::unique_ptr<Base<1>> d1 = std::make_unique<Derived1>();
  std::unique_ptr<Base<2>> d2 = std::make_unique<Derived2>();

  // these fail
//   auto d1 = std::make_unique<Derived1>();
//   auto d2 = std::make_unique<Derived2>();
  std::cout << get(std::move(d1)) << std::endl;
  std::cout << get(std::move(d2)) << std::endl;
}

思路是在get()函数中,当传入派生类unique_ptr时,我想获取基类模板中参数的值。

main() 函数表明,如果我不使用auto 并明确指定基类类型,模板将匹配得很好。但是,如果我切换到auto,则类型变为unique_ptr&lt;DerivedX&gt;,然后它不会编译。

http://cpp.sh/2b4tb

如果我将 unique_ptr 切换为原始指针(即 Base&lt;val&gt;* 而不是 unique_ptr&lt;Base&lt;val&gt;&gt;),一切都会正常工作。如果 C++ 模板包装在另一个传递给函数的模板中,它似乎不处理类型推导?

我在这里缺少一些基本的东西吗?谢谢。

【问题讨论】:

    标签: c++


    【解决方案1】:

    你已经或多或少地回答了你自己的问题。

    当您使用auto 时,您会得到一个std::unique_ptr&lt;DerivedX&gt;。模板中的参数推导仅适用于确切类型。它不进行隐式转换。

    为了使这种推论起作用,编译器首先必须将std::unique_ptr&lt;DerivedX&gt; 转换为std::unique_ptr&lt;Base&lt;val&gt;&gt;,然后在转换后弄清楚val 是什么。

    对您有用的一种方法是为 Base 提供一个您可以访问的静态 constexpr 值。

    #include <memory>
    #include <iostream>
    
    template <int val>
    struct Base {
        static constexpr int my_value = val;
    };
    
    struct Derived1 : public Base<1> {
    };
    
    struct Derived2 : public Base<2> {
    };
    
    template <typename T>
    int get(const T& ptr) {
        return (*ptr).my_value;
        // Same thing but written differently
        // return T::element_type::my_value;
    }
    
    int main()
    {
       auto d1 = std::make_unique<Derived1>();
       auto d2 = std::make_unique<Derived2>();
       std::cout << get(std::move(d1)) << std::endl;
       std::cout << get(std::move(d2)) << std::endl;
    }
    

    【讨论】:

    • 这与自动无关。如果不使用 auto 而只是显式使用 std::unique_ptr 和 std::unique_ptr 问题仍然存在:cpp.sh/242ue 说,你的问题是一个很好的解决方法(即模板解析问题,而不是自动解决)。
    • @higlu 正如我的回答所说,这是模板参数推导的问题。关于auto的部分直接引用OPs代码,只是指出两个例子中d1d2的类型不同,这就是模板推导失败的原因。我真的不认为它可以被合理地误解为好像我说auto 是这里的问题。
    • 谢谢@super!我不知道我可以直接通过static constexpr 烘焙参数信息。直到。话虽如此,虽然我知道模板推导不会进行派生到基础的转换 IIRC,但我不确定为什么 unique_ptr 会中断(不完全是,但你明白了)但如果我将 get() 更改为取原始指针(这也应该是派生到基础的转换)。
    • @NSF 看看Deduction from function call 部分,在Non-deduced context here 之前的最底部。指针转换显然是允许的。
    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 2022-10-20
    • 2011-10-07
    • 2012-08-06
    • 2019-09-03
    • 1970-01-01
    • 2018-05-01
    相关资源
    最近更新 更多