代码之家  ›  专栏  ›  技术社区  ›  alfC

CTAD可以在模板类的成员内部使用吗?

  •  3
  • alfC  · 技术社区  · 2 年前

    C++有这样一个有用的特性,即模板参数隐含在模板类内的代码中 A 。 然而,对于建筑而言,这似乎与CTAD相冲突。

    如何使CTAD优先?

    例如,在这里 f 成员,因为 A. 被解释为 A<T> 哪里 T std::string ,而不是从参数中推导出来的 double

    #include<string>
    
    template<class T>
    struct A {
        A(T const& t) {}
        auto f() {return A{5.0};}  // error here triggered by line 11 `auto a2 = a1.f();`
    };
    
    int main() {
        A a1{std::string{"hello"}};
        auto a2 = a1.f();
    }
    

    https://godbolt.org/z/3nc7nev3o

    2 回复  |  直到 2 年前
        1
  •  5
  •   NathanOliver    2 年前

    你需要使用 ::A 告诉编译器使用该名称 A 从全局范围而不是使用名称 A. 在类范围中,这只是 A<T> 。这会让您:

    #include<string>
    
    template<class T>
    struct A {
        A(T const& t) {}
        auto f() {return ::A{5.0};}  // uses CTAD to return A<double>
    };
    
    int main() {
        A a1{std::string{"hello"}};
        auto a2 = a1.f();
    }
    

    如图所示 live example


    另一种选择是向类类型添加一个私有别名,然后根据需要在函数中使用该别名。这会给你:

    #include<string>
    
    template<class T>
    struct A {
    private:
        template <typename U>
        using NewA = A<U>;
    public:
        A(T const& t) {}
        auto f() {return NewA{5.0};}  // uses CTAD to return A<double>
    };
    
    int main() {
        A a1{std::string{"hello"}};
        auto a2 = a1.f();
    }
    

    可以看到蜜蜂在工作 here

        2
  •  1
  •   alfC    2 年前

    我似乎可以定义一个模板typedef和 希望 CTAD通过它工作。

    #include<string>
    
    template<class T>
    struct A;
    
    template<class T> using A_CTAD = A<T>;
    
    template<class T>
    struct A {
        A(T const& t) {}
        auto f() {return A_CTAD{5.0};}  // error here triggered by line 11 `auto a2 = a1.f();`
    };
    
    int main() {
        A a1{std::string{"hello"}};
        auto a2 = a1.f();
    }
    

    https://godbolt.org/z/hex79s91a

    但与使用老古董相比,这似乎并不是什么大收获 make 作用 https://godbolt.org/z/j3PTW7MWY


    版本2,制作一个内部模板typedef,不错。无需远期申报。

    template<class T>
    struct A {
        A(T const& t) {}
    private:
        template<class TT> using CTAD = A<TT>;
    public:
        auto f() {return CTAD{5.0};}  // error here triggered by line 11 `auto a2 = a1.f();`
    };