单个模板的可变参数模板包 class
Variadic templates pack of a single templated class
有如下例子:
/* Signal Container */
template <typename Ret> class Signal;
template <typename Ret, typename... Args>
class Signal< Ret (Args...) >
{
/* Following Implementation... */
};
/* Emitter Type */
template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig>
class Emitter
{
// using Signals = std::tuple<Sig...>;
/* Following Implementation... */
};
/* Signals */
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
/* Desired Usage */
class MyType : public Emitter<Signal_A, Signal_B, Signal_C>
{
};
我希望能够继承 Emitter
类型,该类型接受 1 个(0?)或更多 Signal
类型的模板参数( 并且仅 Signal
)。 Signal
是一种模板化类型,它的定义因传递给 Emitter
参数包的每种类型而不同。
我在 MinGW 上尝试了当前的方法,但我收到了这些错误消息,我有点迷茫了:
/* Line: template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig> */
main.cpp|15|error: expected 'class' before 'Signal'|
/* Line: template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig> */
main.cpp|15|error: expected '>' before '<' token|
/* Line: class MyType : public Emitter<Signal_A, Signal_B, Signal_C> */
main.cpp|29|error: wrong number of template arguments (3, should be 1)|
/* Linne: class Emitter */
main.cpp|16|error: provided for 'template<template<class Ret, class ... Args> class Signal> class Emitter'|
如果有人能澄清这一点或提供可行的解决方案,我将不胜感激。
可用的编译器:MinGW GCC 4.9.2(还有 5.1.0)
您不必在 class 模板 Emitter
中匹配 Signal
的所有内部类型。您只需声明它是一个接收参数的模板。之后,您将需要重复出现最多 Signal<T>
的最小数量,您可以在您的应用程序中允许。假设最小值是一个,这里有一个解决方案。
/* Signal Container */
template <typename Ret>
class Signal;
template <typename Ret, typename... Args>
class Signal<Ret(Args...)> {};
/* Emitter Type */
template <typename... Args>
class Emitter;
template <typename T>
class Emitter<Signal<T> > {
// definition of class with single signal
};
template <typename T, typename... Args>
class Emitter<Signal<T>, Args...> {
// definition of class with MORE THAN one signal
};
/* Signals */
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
/* Desired Usage */
class MyType : public Emitter<Signal_A, Signal_B, Signal_C> {};
int main() {
MyType x;
}
您无法在 C++11 或 C++14 中以简单的方式完成您想做的事情。概念可能会给我们一些东西,但现在您的模板参数必须是类型、class 模板或值。在您的情况下,您需要一组只能指定为:
的信号
template <typename... Sigs>
class Emitter;
在 class 中,然后您可以使用 static_assert
验证它们是否都是 Signal
:
static_assert(all_true<is_signal<Sigs>::value...>::value, "Emitter must use only Signals");
您必须为 is_signal
编写一个类型特征,并为 all_true
提供一个元函数。可以找到后者的一个示例
我post将此作为答案,因为它确实满足了问题中的要求。即使我标记了正确答案。我认为 post 我的最终方法是合适的。
#include <iostream>
/* Signal Container */
template <typename Ret> class Signal;
template <typename Ret, typename... Args>
class Signal< Ret (Args...) >
{
/* Following Implementation... */
};
namespace {
/* Signal Type Traits */
template < typename T >
struct IsSignal { static constexpr bool Value = false; };
template < typename T >
struct IsSignal< Signal< T > > { static constexpr bool Value = true; };
/* Signal Validation */
template < bool V, typename... Args >
struct AreSignals
{
static constexpr bool Value = V;
};
template < bool V, typename T, typename... Args >
struct AreSignals< V, T, Args... >
{
static constexpr bool Value = AreSignals< V && IsSignal< T >::Value, Args... >::Value;
};
}
/* Emitter Type */
template < typename... Args >
class Emitter
{
// Block unsupported signals
static_assert( AreSignals<true, Args...>::Value, "Unsupported signal type" );
using Signals = std::tuple<Args...>;
/* Following Implementation... */
};
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
class MyType : public Emitter<Signal_A, Signal_B, Signal_C>
{
};
int main(int argc, char **argv)
{
std::cout << AreSignals<true, Signal_A, Signal_B, Signal_C>::Value << "\n"; // 1 (true)
std::cout << AreSignals<true, Signal_A, int, Signal_B, Signal_C>::Value << "\n"; // 0 (false)
return EXIT_SUCCESS;
}
有如下例子:
/* Signal Container */
template <typename Ret> class Signal;
template <typename Ret, typename... Args>
class Signal< Ret (Args...) >
{
/* Following Implementation... */
};
/* Emitter Type */
template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig>
class Emitter
{
// using Signals = std::tuple<Sig...>;
/* Following Implementation... */
};
/* Signals */
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
/* Desired Usage */
class MyType : public Emitter<Signal_A, Signal_B, Signal_C>
{
};
我希望能够继承 Emitter
类型,该类型接受 1 个(0?)或更多 Signal
类型的模板参数( 并且仅 Signal
)。 Signal
是一种模板化类型,它的定义因传递给 Emitter
参数包的每种类型而不同。
我在 MinGW 上尝试了当前的方法,但我收到了这些错误消息,我有点迷茫了:
/* Line: template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig> */
main.cpp|15|error: expected 'class' before 'Signal'|
/* Line: template < template <typename Ret, typename... Args> Signal< Ret (Args...) > ... Sig> */
main.cpp|15|error: expected '>' before '<' token|
/* Line: class MyType : public Emitter<Signal_A, Signal_B, Signal_C> */
main.cpp|29|error: wrong number of template arguments (3, should be 1)|
/* Linne: class Emitter */
main.cpp|16|error: provided for 'template<template<class Ret, class ... Args> class Signal> class Emitter'|
如果有人能澄清这一点或提供可行的解决方案,我将不胜感激。
可用的编译器:MinGW GCC 4.9.2(还有 5.1.0)
您不必在 class 模板 Emitter
中匹配 Signal
的所有内部类型。您只需声明它是一个接收参数的模板。之后,您将需要重复出现最多 Signal<T>
的最小数量,您可以在您的应用程序中允许。假设最小值是一个,这里有一个解决方案。
/* Signal Container */
template <typename Ret>
class Signal;
template <typename Ret, typename... Args>
class Signal<Ret(Args...)> {};
/* Emitter Type */
template <typename... Args>
class Emitter;
template <typename T>
class Emitter<Signal<T> > {
// definition of class with single signal
};
template <typename T, typename... Args>
class Emitter<Signal<T>, Args...> {
// definition of class with MORE THAN one signal
};
/* Signals */
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
/* Desired Usage */
class MyType : public Emitter<Signal_A, Signal_B, Signal_C> {};
int main() {
MyType x;
}
您无法在 C++11 或 C++14 中以简单的方式完成您想做的事情。概念可能会给我们一些东西,但现在您的模板参数必须是类型、class 模板或值。在您的情况下,您需要一组只能指定为:
的信号template <typename... Sigs>
class Emitter;
在 class 中,然后您可以使用 static_assert
验证它们是否都是 Signal
:
static_assert(all_true<is_signal<Sigs>::value...>::value, "Emitter must use only Signals");
您必须为 is_signal
编写一个类型特征,并为 all_true
提供一个元函数。可以找到后者的一个示例
我post将此作为答案,因为它确实满足了问题中的要求。即使我标记了正确答案。我认为 post 我的最终方法是合适的。
#include <iostream>
/* Signal Container */
template <typename Ret> class Signal;
template <typename Ret, typename... Args>
class Signal< Ret (Args...) >
{
/* Following Implementation... */
};
namespace {
/* Signal Type Traits */
template < typename T >
struct IsSignal { static constexpr bool Value = false; };
template < typename T >
struct IsSignal< Signal< T > > { static constexpr bool Value = true; };
/* Signal Validation */
template < bool V, typename... Args >
struct AreSignals
{
static constexpr bool Value = V;
};
template < bool V, typename T, typename... Args >
struct AreSignals< V, T, Args... >
{
static constexpr bool Value = AreSignals< V && IsSignal< T >::Value, Args... >::Value;
};
}
/* Emitter Type */
template < typename... Args >
class Emitter
{
// Block unsupported signals
static_assert( AreSignals<true, Args...>::Value, "Unsupported signal type" );
using Signals = std::tuple<Args...>;
/* Following Implementation... */
};
using Signal_A = Signal<void()>;
using Signal_B = Signal<void(int)>;
using Signal_C = Signal<void(int, float)>;
class MyType : public Emitter<Signal_A, Signal_B, Signal_C>
{
};
int main(int argc, char **argv)
{
std::cout << AreSignals<true, Signal_A, Signal_B, Signal_C>::Value << "\n"; // 1 (true)
std::cout << AreSignals<true, Signal_A, int, Signal_B, Signal_C>::Value << "\n"; // 0 (false)
return EXIT_SUCCESS;
}