考虑以下模板类
class MyClassInterface {
public:
virtual double foo(double) = 0;
}
class MyClass<int P1, int P2, int P3>
: public MyClassInterface {
public:
double foo(double a) {
// complex computation dependent on P1, P2, P3
}
// more methods and fields (dependent on P1, P2, P3)
}
Run Code Online (Sandbox Code Playgroud)
模板参数P1,P2,P3是在限制范围就像从0一些固定值n固定在编译时.
现在我想建立一个像"工厂"的方法
MyClassInterface* Factor(int p1, int p2, int p3) {
return new MyClass<p1,p2,p3>(); // <- how to do this?
}
Run Code Online (Sandbox Code Playgroud)
问题是如何在模板参数仅在运行时知道时如何实现模板类的构造.对于具有非常大的域(如双)的模板参数,同样可能吗?如果可能的解决方案可扩展到使用更多模板参数,请另请考虑.
Bil*_*nch 19
这是你可以做的:
MyClassInterface* Factor(int p1, int p2, int p3) {
if (p1 == 0 && p2 == 0 && p3 == 0)
return new MyClass<0,0,0>();
if (p1 == 0 && p2 == 0 && p3 == 1)
return new MyClass<0,0,1>();
etc;
}
Run Code Online (Sandbox Code Playgroud)
请注意,这甚至无法远程扩展到浮点值.它仅扩展到已知的离散值列表.
我之前也使用过这段代码做一些模板自动生成:
#include <boost/preprocessor.hpp>
#define RANGE ((0)(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)(11)(12))
#define MACRO(r, p) \
if (BOOST_PP_SEQ_ELEM(0, p) == var1 && BOOST_PP_SEQ_ELEM(1, p) == var2 && BOOST_PP_SEQ_ELEM(2, p) == var3 && BOOST_PP_SEQ_ELEM(3, p) == var4) \
actual_foo = foo<BOOST_PP_TUPLE_REM_CTOR(4, BOOST_PP_SEQ_TO_TUPLE(p))>;
BOOST_PP_SEQ_FOR_EACH_PRODUCT(MACRO, RANGE RANGE RANGE RANGE)
#undef MACRO
#undef RANGE
Run Code Online (Sandbox Code Playgroud)
编译器生成如下所示的输出:
if (0 == var1 && 0 == var2 && 0 == var3 && 0 == var4) actual_foo = foo<0, 0, 0, 0>;
if (0 == var1 && 0 == var2 && 0 == var3 && 1 == var4) actual_foo = foo<0, 0, 0, 1>;
if (0 == var1 && 0 == var2 && 0 == var3 && 2 == var4) actual_foo = foo<0, 0, 0, 2>;
if (0 == var1 && 0 == var2 && 0 == var3 && 3 == var4) actual_foo = foo<0, 0, 0, 3>;
if (0 == var1 && 0 == var2 && 0 == var3 && 4 == var4) actual_foo = foo<0, 0, 0, 4>;
if (0 == var1 && 0 == var2 && 0 == var3 && 5 == var4) actual_foo = foo<0, 0, 0, 5>;
if (0 == var1 && 0 == var2 && 0 == var3 && 6 == var4) actual_foo = foo<0, 0, 0, 6>;
if (0 == var1 && 0 == var2 && 0 == var3 && 7 == var4) actual_foo = foo<0, 0, 0, 7>;
if (0 == var1 && 0 == var2 && 0 == var3 && 8 == var4) actual_foo = foo<0, 0, 0, 8>;
etc...
Run Code Online (Sandbox Code Playgroud)
此外,请注意,使用此方法,使用4个变量,每个变量超过13个值,您将使编译器实例化此函数的28561个副本.如果您的n为50,并且您仍然有4个选项,那么您将实例化6250000个函数.这可以使SLOW编译.
jon*_*son 11
如果宏不是你的东西那么你也可以使用模板生成if-then-else的:
#include <stdexcept>
#include <iostream>
const unsigned int END_VAL = 10;
class MyClassInterface
{
public:
virtual double foo (double) = 0;
};
template<int P1, int P2, int P3>
class MyClass : public MyClassInterface
{
public:
double foo (double a)
{
return P1 * 100 + P2 * 10 + P3 + a;
}
};
struct ThrowError
{
static inline MyClassInterface* create (int c1, int c2, int c3)
{
throw std::runtime_error ("Could not create MyClass");
}
};
template<int DEPTH = 0, int N1 = 0, int N2 = 0, int N3 = 0>
struct Factory : ThrowError {};
template<int N2, int N3>
struct Factory<0, END_VAL, N2, N3> : ThrowError {};
template<int N1, int N3>
struct Factory<1, N1, END_VAL, N3> : ThrowError {};
template<int N1, int N2>
struct Factory<2, N1, N2, END_VAL> : ThrowError {};
template<int N1, int N2, int N3>
struct Factory<0, N1, N2, N3>
{
static inline MyClassInterface* create (int c1, int c2, int c3)
{
if (c1 == N1)
{
return Factory<1, N1, 0, 0>::create (c1, c2, c3);
}
else
return Factory<0, N1 + 1, N2, N3>::create (c1, c2, c3);
}
};
template<int N1, int N2, int N3>
struct Factory<1, N1, N2, N3>
{
static inline MyClassInterface* create (int c1, int c2, int c3)
{
if (c2 == N2)
{
return Factory<2, N1, N2, 0>::create (c1, c2, c3);
}
else
return Factory<1, N1, N2 + 1, N3>::create (c1, c2, c3);
}
};
template<int N1, int N2, int N3>
struct Factory<2, N1, N2, N3>
{
static inline MyClassInterface* create (int c1, int c2, int c3)
{
if (c3 == N3)
{
return new MyClass<N1, N2, N3> ();
}
else
return Factory<2, N1, N2, N3 + 1>::create (c1, c2, c3);
}
};
MyClassInterface* factory (int c1, int c2, int c3)
{
return Factory<>::create (c1, c2, c3);
}
Run Code Online (Sandbox Code Playgroud)
由于测试是嵌套的,因此它应该比sharth的宏解决方案更有效.
您可以通过添加更多深度案例将其扩展到更多参数.
这是不可能的,模板在编译时实例化.
当你有一个可执行文件时,你只有类(这些模板的特定实例),不再有模板.
如果您在编译时不知道值,则无法获得这些值的模板.