使用派生类型的类模板作为模板模板参数

时间:2021-02-26 01:26:25

标签: c++ templates

这是我要完成的工作的示例:

#include <iostream>

using namespace std;

template <typename Tmsg>
class MessageParser{
    public:
        virtual Tmsg Deserialize(const char *buf, size_t len);
};

class JsonParser : MessageParser<int>{
    public:
        int Deserialize(const char *buf, size_t len) override { return 1; };
};

template <class Tmsg>
using rpc_handler_t = void (*)(Tmsg);

template <typename Tmsg, template <typename> class Tparser>
class RpcServer{
    public:
        RpcServer(Tparser<Tmsg> parser) : _parser(parser) {};
        Tparser<Tmsg> _parser;
        void RegisterHandler(rpc_handler_t<Tmsg> handler);
};

int main()
{
    JsonParser parser;
    RpcServer<int, JsonParser> server(parser);

    cout << "Hello World";
}

首先,类模板参数推导似乎是 C++17 的特性。我被 C++11 困住了。编写 RpcServer(parser) 并将其识别为 RpcServer<int, JsonParser> 真是太好了。

以上给了我:

class "JsonParser" is not a class template

好吧,这是真的。但这又有什么关系呢?为什么 JsonParser 作为 MessageParser<JsonObject> 不满足模板?

1 个答案:

答案 0 :(得分:0)

它不满足模板,因为这个语法无效:

JsonParser<int> parser;

如您所见,它无法编译。它的基类是什么以及该基类的性质无关紧要。 JsonParser 本身不是模板。你不能向它发送模板参数。

如果可能,这段代码会做什么?

template<typename T>
struct Base {
    T value = {};
};

// Derived extend `Base<int>`. Therefore Derived has a int value
struct Derived : Base<int> {};

template<template<typename> TT>
void do_stuff() {
    TT<float> g;
    std::cout << g.value;
}

do_stuff<Derived>(); // prints a int or a float?

您只能将模板类发送到模板模板参数。您必须将 JsonParser 设为模板:

template<typename T>
class JsonParser : MessageParser<T> {
    public:
        T Deserialize(const char *buf, size_t len) override { return 1; };
};

或者让你的类型接收一个普通类型:

template <typename Tparser>
class RpcServer{
    public:
        RpcServer(Tparser parser) : _parser(parser) {};
        Tparser _parser;
};

要返回 Tmsg,只需添加一个 typedef,或使用 decltype

template<typename Tmsg>
struct MessageParser {
    using MsgType = Tmsg;

    // ...
};

template <typename Tparser>
class RpcServer{
    using Tmsg = typename Tparser::MsgType;
    
    // or using decltype:
    using Tmsg = decltype(std::declval<Tparser>().Deserialize("", 0));

    public:
        RpcServer(Tparser parser) : _parser(parser) {};
        Tparser _parser;
};

我建议使用简单类型作为模板参数。