模板class使用参数包时如何传递其他模板参数?
How to pass other template parameter when template class uses parameter pack?
我想创建模板 class,为作为模板参数传递的每种类型实现 print()
方法。
类似的东西:
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
X x<int, double, Interface>;
class X
有 public 方法 void print()
并且有效。
完整代码如下:
#include <iostream>
#include <type_traits>
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
template <typename... Args>
class X;
template <typename Interface>
class X<Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value, "Last argument should be an interface");
public:
X(Printer printer) {}
using Interface::print;
};
template <typename Arg, typename... Args>
class X<Arg, Args...> : public X<Args...>
{
using Parent = X<Args...>;
public:
using Parent::print;
X(Printer printer_): Parent(printer), printer{printer_} {}
void print(Arg arg) override { printer.print(arg); }
private:
Printer printer;
};
int main()
{
Printer printer;
X<double, int, Interface> x(printer);
x.print(5);
}
如您所见,class X
使用 Printer
class 但问题是我想将 Printer
作为模板参数...
可能吗?怎么做?
As you see class X uses Printer class but the problem is that I would like to have Printer as a template parameter...
Is it possible? How to do that?
抱歉,但是...我没有看到问题(Story Teller 建议进行极大的简化:在地面案例中放置一个 Printer
对象)
template <typename...>
class X;
template <typename Printer, typename Interface>
class X<Printer, Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value,
"Last argument should be an interface");
public:
X (Printer p0) : printer{p0}
{ }
using Interface::print; // why?
protected:
Printer printer;
};
template <typename Printer, typename Arg, typename... Args>
class X<Printer, Arg, Args...> : public X<Printer, Args...>
{
using Parent = X<Printer, Args...>;
public:
using Parent::print;
using Parent::printer;
X(Printer printer_): Parent{printer_} {}
void print(Arg arg) override { printer.print(arg); }
};
// ....
X<Printer, double, int, Interface> x(printer);
题外话:注意:您正在使用printer
未初始化
X(Printer printer_): Parent(printer), printer{printer_} {}
我想你应该写 Parent(printer_)
- 假设需要多态接口。
- 多态性降低了可变参数模板扩展的价值
- 保留对封装打印机的操作延迟
可能的解决方案:
#include <iostream>
#include <type_traits>
// Abstract interface
class PrintInterface
{
public:
virtual ~PrintInterface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
// An implmentation of PrintInterface that defers to PrinterType
template<class PrinterType>
class ImplementPrintInterface : public PrintInterface
{
public:
ImplementPrintInterface(PrinterType printer)
: printer_(std::move(printer))
{}
virtual void print(int x) override
{
printer_.print(x);
}
virtual void print(double x) override
{
printer_.print(x);
}
private:
PrinterType printer_;
};
// An implementation of a thing that prints ints and doubles.
// This happens to match PrintInterface but there is no inheritance
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
// X *is a* PrinterInterface that *uses a* PrinterType
template <typename PrinterType>
class X : public ImplementPrintInterface<PrinterType>
{
public:
X(PrinterType printer = PrinterType())
: ImplementPrintInterface<PrinterType>(std::move(printer))
{}
};
int main()
{
Printer printer;
X<Printer> x(printer);
x.print(5);
}
我想创建模板 class,为作为模板参数传递的每种类型实现 print()
方法。
类似的东西:
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
X x<int, double, Interface>;
class X
有 public 方法 void print()
并且有效。
完整代码如下:
#include <iostream>
#include <type_traits>
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
class Interface
{
public:
virtual ~Interface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
template <typename... Args>
class X;
template <typename Interface>
class X<Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value, "Last argument should be an interface");
public:
X(Printer printer) {}
using Interface::print;
};
template <typename Arg, typename... Args>
class X<Arg, Args...> : public X<Args...>
{
using Parent = X<Args...>;
public:
using Parent::print;
X(Printer printer_): Parent(printer), printer{printer_} {}
void print(Arg arg) override { printer.print(arg); }
private:
Printer printer;
};
int main()
{
Printer printer;
X<double, int, Interface> x(printer);
x.print(5);
}
如您所见,class X
使用 Printer
class 但问题是我想将 Printer
作为模板参数...
可能吗?怎么做?
As you see class X uses Printer class but the problem is that I would like to have Printer as a template parameter...
Is it possible? How to do that?
抱歉,但是...我没有看到问题(Story Teller 建议进行极大的简化:在地面案例中放置一个 Printer
对象)
template <typename...>
class X;
template <typename Printer, typename Interface>
class X<Printer, Interface> : public Interface
{
static_assert(std::is_abstract<Interface>::value,
"Last argument should be an interface");
public:
X (Printer p0) : printer{p0}
{ }
using Interface::print; // why?
protected:
Printer printer;
};
template <typename Printer, typename Arg, typename... Args>
class X<Printer, Arg, Args...> : public X<Printer, Args...>
{
using Parent = X<Printer, Args...>;
public:
using Parent::print;
using Parent::printer;
X(Printer printer_): Parent{printer_} {}
void print(Arg arg) override { printer.print(arg); }
};
// ....
X<Printer, double, int, Interface> x(printer);
题外话:注意:您正在使用printer
未初始化
X(Printer printer_): Parent(printer), printer{printer_} {}
我想你应该写 Parent(printer_)
- 假设需要多态接口。
- 多态性降低了可变参数模板扩展的价值
- 保留对封装打印机的操作延迟
可能的解决方案:
#include <iostream>
#include <type_traits>
// Abstract interface
class PrintInterface
{
public:
virtual ~PrintInterface() = default;
virtual void print(int) = 0;
virtual void print(double) = 0;
};
// An implmentation of PrintInterface that defers to PrinterType
template<class PrinterType>
class ImplementPrintInterface : public PrintInterface
{
public:
ImplementPrintInterface(PrinterType printer)
: printer_(std::move(printer))
{}
virtual void print(int x) override
{
printer_.print(x);
}
virtual void print(double x) override
{
printer_.print(x);
}
private:
PrinterType printer_;
};
// An implementation of a thing that prints ints and doubles.
// This happens to match PrintInterface but there is no inheritance
struct Printer
{
void print(int i) {std::cout << i << std::endl; }
void print(double d) {std::cout << d << std::endl; }
};
// X *is a* PrinterInterface that *uses a* PrinterType
template <typename PrinterType>
class X : public ImplementPrintInterface<PrinterType>
{
public:
X(PrinterType printer = PrinterType())
: ImplementPrintInterface<PrinterType>(std::move(printer))
{}
};
int main()
{
Printer printer;
X<Printer> x(printer);
x.print(5);
}