【问题标题】:Why C++17 class template argument deduction fails?为什么 C++17 类模板参数推导失败?
【发布时间】:2020-09-24 15:15:33
【问题描述】:

C++17 提供class template argument deduction

我有以下小例子(你可以粘贴到启用 C++17 的 onlinegdb,没问题)在某些情况下它会失败,但我不知道为什么:

#include <iostream>
enum class Res{
    ResA,
    ResB
};

template<Res>
class B{   
};

template<Res T>
class A{
    //If I remove this construtor, template type deduction will not work anymore
    public:   
    A(B<T> b){       
    }
};

template<>
class A<Res::ResA>{
    public:
    A(B<Res::ResA> b){
        std::cout<<"A res A\n";
    }  
};

int main()
{
    B<Res::ResA> b;
    A a(b);
}

上面的代码有效。但是,一旦我将A 的构造函数更改为模板特化中的任何其他构造函数,模板参数推导将不起作用,A 必须由A&lt;Res::ResA&gt; 初始化。

我不知所措。为什么会这样?感谢您的任何想法!

【问题讨论】:

  • 我猜编译器忽略了参数推导的特化。所以它不可能知道 T 应该是什么。
  • FWIW,为了让自己保持清醒,当你有模板专业化时,假装它不存在。在主模板被解析之前,它们实际上并没有发挥作用,并且仅与与模板专业化匹配的主模板一起使用。在那之前,它只是那些特定模板参数的配方。
  • Elliot,这在语义上有什么不同?
  • @Elliott 在这种情况下没有推论,模板参数只有一个默认值,因此它只会使代码适用于该特定专业化。这并不能真正回答问题或解决 CTAD 的任何问题。它只会编译这个特定的 sn-p 代码。
  • @Elliott 不,编译器不会推断出任何东西。您明确告诉它模板参数应该是 Res::ResA 如果它不可推导。如果您要添加另一个模板专业化A&lt;Res::ResB&gt;,它在其构造函数中采用B&lt;Res::ResB&gt;,它将无法工作,因为不涉及实际扣除。只有一个默认值。

标签: c++ templates c++17 template-argument-deduction class-template


【解决方案1】:

生成的CTAD 仅来自 primary 模板。

如果您不想在主模板中添加该构造函数,您仍然可以提供自定义推导指南。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 2012-09-15
    • 1970-01-01
    • 2018-04-28
    • 2014-09-22
    相关资源
    最近更新 更多