簡體   English   中英

使用 class 模板的派生類型作為模板模板參數

[英]Use derived type of class template as template template parameter

這是我正在嘗試完成的示例:

#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";
}

首先,看起來class模板參數推導是一個C++17特性。 我被 C++11 困住了。 編寫RpcServer(parser)並將其識別為RpcServer<int, JsonParser>了。

以上給了我:

class "JsonParser" is not a class template

好吧,這是真的。 但這有什么關系? 為什么JsonParser作為MessageParser<JsonObject>不滿足模板?

它不滿足模板,因為此語法無效:

JsonParser<int> parser;

如您所見,它無法編譯。 它的基礎 class 和基礎 class 的性質是什么並不重要。 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;
};

我建議使用簡單類型作為模板參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM