gpt4 book ai didi

c++ - 使用子类中的类型定义扩展模板类

转载 作者:行者123 更新时间:2023-11-30 04:44:51 24 4
gpt4 key购买 nike

我模仿std::enable_shared_from_this 创建了一个模板类,但是我让这个类在它的子类中使用类型定义。很遗憾!虽然我用的是typename,但是编译之后,

// 
// https://ideone.com/eYCBHW http://ideone.com/eYCBHW
#include <iostream>
#include <set>
#include <map>
using namespace std;

template<class _S> struct A {
};

template<class _Subclass>
class Global {
public:
typedef typename _Subclass::connection_t connection_t;
//std::map<std::string, _Subclass::connection_t> connections;
//std::set<_Subclass::connection_t> connections;
//using typename _Subclass::connection_t;
//typename _Subclass::connection_t* connections;
//connection_t* connections;
};

class CConnection {};

class SConnection;

class Client : public Global<Client> {
public:
typedef CConnection connection_t;
};

#if 0
class Server : public Global<Server> {
public:
typedef SConnection connection_t;
};
#endif

class SConnection {};

int main() {
// your code goes here
return 0;
}

GCC 提示:

prog.cpp: In instantiation of ‘class Global<Client>’:
prog.cpp:25:23: required from here
prog.cpp:14:43: error: invalid use of incomplete type ‘class Client’
typedef typename _Subclass::connection_t connection_t;
^~~~~~~~~~~~
prog.cpp:25:7: note: forward declaration of ‘class Client’
class Client : public Global<Client> {
^~~~~~

如何解决?

引用资料

最佳答案

在类级别有一个 typedef 要求模板参数是完整的类型。如果作为参数提供的类型本身实际上具有某种等效的 typedef,编译器将如何检查?

类似地,以下将失败:

class C;
using G = Global<C>; // C is not a complete type!
class C // too late...
{
// ...
};

curiously recurring template pattern 有问题,这就是您要实现的,在您尝试派生时,该类尚未完成,就像我上面的示例一样:

class Client : public Global<Client> // client is not yet complete!
{
}; // only HERE, it will get complete, but that's too late for above

但有没有想过,为什么成员变量在成员函数中是已知的,即使是在函数之后声明的?那是因为

class C
{
void f() { n = 12; }
int n = 10;
};

被编译就好像它是这样写的:

class C
{
inline void f();
int n = 10;
};

void C::f() { n = 12; } // n is known now!

这同时也是您可以按预期方式使用模板参数的地方线索:

template<class T> // different name used! *)
class Global
{
public:
void f()
{
typedef typename T::connection_t connection_t; // possible here!
// (similar to why you can use the static cast as in the link provided)
}
};

不过,这对您的成员(member)没有帮助:

std::map<std::string, typename T::connection_t> connections;
// ^ additionally was missing, but won't help either

T 此时仍未完成。

不过,在评论中,您似乎只使用了连接类型。如果您出于 typedef 以外的任何原因不需要客户端或服务器类,您可以非常简单地解决问题:

template<class T> // different name used! *)
class Global
{
std::map<std::string, T> connections;
// ^ use T directly
};

class Client : public Global<CConnection>
// ^ make sure it is defined BEFORE
{
// ...
};

否则,您需要退回到其他方式,例如。 G。 pimpl pattern ,在这里您可以让实现类从模板继承。

*) 以下划线开头后跟大写字母的标识符,以及包含两个后续标识符的标识符,保留用于实现(即供编译器使用)。定义您自己的此类行为会产生未定义的行为。


编辑(从评论中窃取):

如果您需要 Global 中的客户端或服务器,您也可以将两者作为单独模板参数提供:

template <typename Base, typename Connection>
{
// use Connection directly, e. g. for member definitions
// and Base within member functions as mandated by CRTP
};

class Client : public Global<Client, CConnection>
{ /* ... */ };

关于c++ - 使用子类中的类型定义扩展模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57546714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com