bra*_*ing 18 c++ crtp template-meta-programming c++14
我有这个玩具示例,
template <typename TChild>
struct Base {
template <typename T>
using Foo = typename TChild::template B<T>;
};
struct Child : Base<Child> {
template <typename T>
using B = T;
};
using Bar = Child::Foo<int>;
Run Code Online (Sandbox Code Playgroud)
无法编译。目的是我有一个父类,它提供基于子类成员的类型计算。子类是通过 CRTP 提供的。然而线
using Foo = typename TChild::template B<T>;
Run Code Online (Sandbox Code Playgroud)
无法编译:
<source>: In instantiation of 'struct Base<Child>':
<source>:16:16: required from here
<source>:13:11: error: invalid use of incomplete type 'struct Child'
13 | using Foo = typename TChild::template B<T>;
| ^~~
<source>:16:8: note: forward declaration of 'struct Child'
16 | struct Child : Base<Child> {
| ^~~~~
Run Code Online (Sandbox Code Playgroud)
我期待这样的构造起作用是天真吗?
Evg*_*Evg 10
让我发布另一种方法来做到这一点:
template<typename TChild, class T>
struct GetB {
using Type = typename TChild::template B<T>;
};
template<typename TChild>
struct Base {
template<typename T>
using Foo = typename GetB<TChild, T>::Type;
};
struct Child : Base<Child> {
template<typename T>
using B = T;
};
Run Code Online (Sandbox Code Playgroud)
我没有语言律师类型的解释为什么这有效,但它应该与具有额外的间接级别有关。当编译器看到
using Foo = typename TChild::template B<T>;
Run Code Online (Sandbox Code Playgroud)
它可以(并且将会)在此时检查和抱怨使用了不完整的类型。然而,当我们将 access 包装B<T>成一个函数或结构体时,
using Foo = typename GetB<TChild, T>::Type;
Run Code Online (Sandbox Code Playgroud)
那么此时我们没有访问内部TChild,我们只是使用它的名称,这很好。
CRTP 的问题是派生类在 CRTP 定义中不完整,因此您不能使用其using.
在
template <typename T>
using Foo = typename TChild::template B<T>;
Run Code Online (Sandbox Code Playgroud)
TChild将需要因::。TChild是不依赖模板的T,所以第一遍检查应该做(但没有)您可能会使用外部特征来处理这种情况
template <typename C, typename T>
struct Traits_For_Base
{
using type = typename C::template B<T>;
};
template <typename TChild>
struct Base {
template <typename T>
using Foo = typename Traits_For_Base<TChild, T>::type;
};
Run Code Online (Sandbox Code Playgroud)
Traits_For_Base<TChild, T>是相关的T,所以没什么可用于第一遍检查做。并且,通过第二次通过检查(依赖于T),Child将完成。
或者您可以更改别名以使其类型依赖于类的模板参数Base:
template <typename TChild>
struct Base {
template <typename T,
typename C = TChild,
std::enable_if_t<std::is_same_v<C, TChild>, int> = 0> // To avoid hijack
using Foo = typename C::template B<T>;
};
Run Code Online (Sandbox Code Playgroud)
C是依赖模板的,所以不能在第一阶段进行检查。
| 归档时间: |
|
| 查看次数: |
824 次 |
| 最近记录: |