CTAD 是否可以在模板类的成员中使用?

Can CTAD be used inside a member of the template class?

提问人:alfC 提问时间:7/24/2023 最后编辑:alfC 更新时间:7/24/2023 访问量:102

问:

C++ 具有这个有用的功能,它表示模板参数隐含在模板类内的代码中。 然而,对于建筑来说,这似乎与CTAD相冲突。A

如何使 CTAD 优先?

例如,在这里,成员中存在错误,因为被解释为 where is ,而不是从参数 中推导出来。fAA<T>Tstd::stringdouble

#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

C++ C++20 类模板 CTAD

评论

1赞 Dmitry 7/24/2023
在里面使用模板 lambda ?像这样f
0赞 alfC 7/24/2023
@Dmitry,这就像有一个功能,但谢谢!make_A
0赞 Dmitry 7/24/2023
是的,事实上我不建议使用它!用户定义的扣除指南可以很容易地打破预期的行为

答:

5赞 NathanOliver 7/24/2023 #1

您需要 use 告诉编译器使用全局作用域中的名称,而不是使用类作用域中的名称,而类作用域中的名称只是 的简写。这为您提供了:::AAAA<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();
}

如这个实时示例所示。


另一种选择是将私有别名添加到类类型,然后根据需要在函数中使用该别名。这为您提供了:

#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();
}

可以看到蜜蜂在这里工作

评论

0赞 alfC 7/24/2023
嗯,是的,这行得通。godbolt.org/z/hvG1r9EdT。但是,现在该类需要知道它所属的命名空间。不理想。
1赞 NathanOliver 7/24/2023
@alfC 如果你正在定义类,你不知道你在哪个命名空间中吗?
0赞 alfC 7/24/2023
是的,但是如果我以后重构命名空间,我必须更改内部结构。
1赞 NathanOliver 7/24/2023
@alfC我明白了。我刚刚添加了另一个选项
0赞 alfC 7/24/2023
是的,我同时发现了它。(我的回答中有第 2 版)。干杯!
1赞 alfC 7/24/2023 #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

但与使用良好的旧函数相比,这似乎并没有太大的收获。https://godbolt.org/z/j3PTW7MWYmake


版本 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();`
};