使用外部定义的模板类型作为模板参数的通用模板的模板别名

问题描述 投票:0回答:1

我想采用一个定义良好的模板类,该类依赖于boost :: signals2并将其抽象为更深的通用层,该通用层可以消除依赖关系,允许使用其他实现,但仍允许使用更高级别的功能取决于更通用的接口,而不是更具体的接口。在我的重构中,我完全陷入困境。而且,我已经知道我在这方面还有些不足。我今年才开始真正地学习C ++。但是,这有点有趣。但是,我对模板的了解缺少一些东西。首先,我正在使用的库将使用C ++ 17,我使用的是clang ++(Mac),具体取决于Boost〜1.7.2 Signals2。

请考虑以下摘录:

#include <boost/signals2.hpp>

template<typename Functional_T, typename Return_T, typename ...Args_T>
using SignalHandler = typename Functional_T::template Functional_T<Return_T(Args_T...)>;

template<typename Connection_T>
struct SignalConnection; //no issues here, just wraps a private Connection_T with a getter/setter

template<typename Connection_T, typename Functional_T, typename Return_T, typename ...Args_T>
struct ISignalEmitter
{
protected:
    virtual Return_T trigger(Args_T ...args) = 0;
public:
    virtual void disconnectAll() = 0;
    virtual SignalConnection<Connection_T> onSignal(SignalHandler<Functional_T, Return_T, Args_T...> &signalHandler) = 0;
    virtual void cancelOnSignal(const SignalConnection<Connection_T> &connection) = 0;
};

但是这是我完全陷入困境的地方。我想定义的东西看起来像这样:

template<typename Return_T, typename ...Args_T>
using BoostSignals2SignalHandler = SignalHandler<boost::signals2::slot, Return_T, Args_T...>;

而且我想我们都知道会发生什么。 slot需要模板参数。那么我该如何构造它才能起作用?我已经尝试过各种方法,但是都被卡住了。我的下一个猜测是:

template<typename Return_T, typename ...Args_T>
using BoostSignals2SignalHandler = SignalHandler<template boost::signals2::slot::template, Return_T, Args_T...>;

我讨厌问,但是我知道我不能成为第一个尝试解决这个谜语的人。而且必须有一种以一种易于理解的方式思考这些模板的方法,而不仅仅是猜测和测试。我有一个模板别名BoostSignals2SignalHandler,它是SignalHandler的特定版本减去第一个模板参数,再使用一个现有模板作为更通用模板的特定模板参数。

我会问,“这是糟糕的设计吗?”,但是我觉得这个概念足以解决我要解决的问题。我只是不知道该怎么做。谁能指出我正确的方向?再次,我讨厌问。弄清楚这个问题真让人头疼。预先感谢!

c++ templates variadic-templates type-alias
1个回答
0
投票
而不是将模板参数列出为Return_T, Args_T...,我将遵循Signals2示例,并使用一个函数类型的单个参数,例如Return_T(Args_T...)中的SignalHandler

然后我们只需将Functional_T更改为模板模板参数。

template<template <typename> typename Functional_T, typename Signature_T> using SignalHandler = Functional_T<Signature_T>;

现在,传递给SignalHandler的第一个参数必须是可以使用1个模板参数实例化的模板。由于您使用的是c++17,因此我们也可以传递带有更多参数的模板,只要它们具有默认值即可。

为了获得Return_T中的Args_T...ISignalEmitter,我们使用了部分专业化。

template<typename Connection_T, template <typename> typename Functional_T, typename Signature_T> struct ISignalEmitter; // Base declaration to match the specialization against template<typename Connection_T, template <typename> typename Functional_T, typename Return_T, typename ...Args_T> struct ISignalEmitter<Connection_T, Functional_T, Return_T(Args_T...)> // Matching Return_T and Args_T against Signature_T { protected: virtual Return_T trigger(Args_T ...args) = 0; public: virtual void disconnectAll() = 0; virtual SignalConnection<Connection_T> onSignal(SignalHandler<Functional_T, Return_T(Args_T...)> &signalHandler) = 0; virtual void cancelOnSignal(const SignalConnection<Connection_T> &connection) = 0; };

此时,您可以像这样定义BoostSignals2SignalHandler

template<typename Signature_T> using BoostSignals2SignalHandler = SignalHandler<boost::signals2::slot, Signature_T>; using MySignalHandler = BoostSignals2SignalHandler<void()>;

© www.soinside.com 2019 - 2024. All rights reserved.