c++17 推断指南(deduction guide)

 
 
namespace _nmsp2
{
    template<typename T>
    struct A
    {
        A(T val1, T val2)
        {
            cout << "A::A(T val1,T val2)执行了!" << endl;
        }

        A(T val)
        {
            cout << "A::A(T val)执行了!" << endl;
        }
    };
    template<typename T>
    A(T)->A<T>;
}
namespace _nmsp3
{
    template<typename T>
    struct B
    {
        T m_b;
        T m_b2;
    };
    template<typename T>
    B(T)->B<T>;

    template<typename T>
    B(T,T)->B<T>;
}

 

c++17新概念:主要用来在推断类模板参数时提供推断指引。
(1)隐式的推断指南
           针对类模板A的每个构造函数,都有一个隐式的模板参数推断机制存在,这个机制,被称为隐式的推断指南
            template<typename T>
            A(T,T)->A<T>;
              表达出现->左侧部分内容或者形式时,请推断成->右侧的类型。右侧类型也被称为“指南类型”
                 ->左侧部分:该推断指南所对应的构造函数的函数声明,多个参数之间用,分隔。
                ->右侧部分:类模板名,接着一个尖括号,尖括号中是模板参数名。
            整个推断指南的含义:当用调用带两个参数的构造函数通过类模板A创建相关对象时,请用所提供的构造函数的实参来推断类模板A的模板参数类型,
           一句话:推断指南的存在意义就是让编译器 能够把模板参数的类型推断出来。
            template<typename T>
            A(T,T)->A<double>;
           那么:A aobj1(15, 16);代码行 相当于A<double> aobj1(15, 16);
(2)自定义的推断指南
            _nmsp3::B bobj3{ 15 }; 不报错的原因
                a)类B是聚合类。 是可以通过{}初始化的
                b)B bobj3{ 15 }这种形式正好就相当于调用了类模板B的带一个参数(15)的构造函数,尽管类模板B中实际并不存在构造函数。
                c)因为template<typename T>B(T)->B<T>;推断指南的存在,当调用了类模板B带一个参数的构造函数时,推断出来的类型为B<T>,所以
                   最终推断出来的类型为B<int>类型。
 

当我们定义一个模板类或者模板函数时,有时候编译器可能无法准确地推导模板参数,或者存在多个可能的推导结果,这时候就需要使用推断指南来明确告诉编译器我们期望的推导结果。

举例说明:

假设我们有一个模板类 Pair,用于表示一对值。它有两个模板参数,分别表示这对值的类型。现在我们希望在传入两个参数时,编译器可以自动推导出这两个参数的类型,并实例化 Pair 类。但是,由于模板参数推导的规则,编译器可能无法准确地推导出这两个参数的类型,或者存在多个可能的推导结果。

这时候,我们可以使用推断指南来帮助编译器更准确地推导模板参数。例如:

cppCopy Code
template<typename T, typename U>
class Pair {
public:
    T first;
    U second;
    
    Pair(T f, U s) : first(f), second(s) {}
};

如果我们使用如下方式创建一个 Pair 对象:

Pair p(5, 3.14);

编译器可能无法准确推导出 Pair 的模板参数类型,因为 5 可以是 intdoublefloat 等类型,而 3.14 可以是 doublefloat 类型。

为了明确告诉编译器我们期望的推导结果,我们可以提供一个推断指南,如下所示:

template<typename T, typename U>
Pair(T, U) -> Pair<T, U>;

这个推断指南告诉编译器,当我们传入两个参数时,应该推导出模板参数类型为 TU,从而实例化 Pair<T, U> 类。

通过使用推断指南,我们可以确保编译器能够正确推导模板参数,从而避免模板实例化过程中可能出现的错误或二义性。

 

template<typename T>
class A
{
public:
    A(T const& t):s(t) {}
    T& show() { return s; }
private:
    T s;
};

//  推断指引
A(const char*)->A<std::string>;
A(bool)->A<int>;
A(int)->A<char>;

int main()
{
    A Int{40};  //  input int
    cout << typeid(Int.show()).name() << endl;  //  output char
    A Bool{ true };  //  input bool
    cout << typeid(Bool.show()).name() << endl;  //  output int
    A str{ "ssssss" };  //  input char[]
    cout<<typeid(str.show()).name()<<endl;  //  output std::string
    return 0;
}

 

posted @ 2024-05-07 14:46  白伟碧一些小心得  阅读(234)  评论(0编辑  收藏  举报