我正在使用第 3 方库中的一个类,它看起来像,
template <typename A = DefaultT, typename B = DefaultT, typename C = DefaultT, typename D = DefaultT, typename E = DefaultT, typename F = DefaultT>
class Vertex {};
我想在运行时根据条件使用此类的部分特化,例如,
class MyA {};
class MyB {};
class MyC {};
class MyD {};
bool useA, useB, useC, useD; //these booleans change at runtime
// I want to specialize Vertex depending on the above booleans
// The below line shouldn't compile, this is just to give an idea
typedef typename Vertex <useA ? MyA : DefaultT, useB ? MyB : DefaultT,
useC ? MyC : DefaultT, useD ? MyD : DefaultT> MyVertex;
我想有条件地选择我想要特化的模板参数。 我不确定这个问题是否有一个术语,我怀疑它是多重调度的一种。
一个简单的方法是编写 15 (2^4 -1) 个类,例如,
typedef typename Vertex <MyA> MyVertexWithA;
typedef typename Vertex <DefaultT, MyB> MyVertexWithB;
typedef typename Vertex <MyA, MyB> MyVertexWithAB; //and so on...until
typedef typename Vertex <MyA, MyB, MyC, MyD> MyVertexWithABCD;
问题变得更加复杂,因为我必须使用一个使用专门顶点类的“网格”类
template <typename VertexClass, typename Others>
class Mesh {};
现在,如果我继续编写 15 个类,那么我将不得不为每种不同的网格类型再编写 15 行。并且在使用 Mesh 类的地方变得越来越复杂。
我坚信这必须由我或编译器来完成。我的问题:
- 我想知道是否有办法让编译器为我完成这项工作?
- C++11 是否有更好的机制来处理这种情况? 谢谢。
最佳答案
答案是否定的。如果条件在运行时发生变化,那么您不能根据这些条件专门化/实例化模板,它们需要是常量表达式(毕竟,编译器在编译器时执行此工作,在程序开始运行之前,所以使用运行时表达式是不行的)。如果它们是在编译时确定的,那么您可以结合使用 constexpr
技巧和 std::conditional
.
正如@Karloy Horvath 提到的,您还可以执行称为标签调度的操作,类似于下面的示例:
#include <iostream>
struct tag_yes{};
struct tag_no{};
template <typename T> void f_tag();
template <>
void f_tag<tag_yes>() // specializations
{
std::cout << "YES" << std::endl;
}
template <>
void f_tag<tag_no>()
{
std::cout << "NO" << std::endl;
}
void f(bool condition)
{
if(condition)
f_tag<tag_yes>(); // call the YES specialization
else
f_tag<tag_no>(); // call the NO specialization
}
int main()
{
bool condition = true;
f(condition); // dispatch to the "right" template function
}
或者,您甚至可以推导出标签(这就是标准 C++ 算法与各种迭代器类型一起工作的方式)
#include <iostream>
#include <type_traits>
struct Foo
{
using tag = std::true_type;
};
struct Bar
{
using tag = std::false_type;
};
template <typename T> void f_tag();
template <>
void f_tag<std::true_type>() // specializations
{
std::cout << "YES" << std::endl;
}
template <>
void f_tag<std::false_type>()
{
std::cout << "NO" << std::endl;
}
template <typename T>
void f(const T&)
{
f_tag<typename T::tag>(); // dispatch the call
}
int main()
{
Foo foo;
Bar bar;
f(foo); // dispatch to f_tag<std::false_type>
f(bar); // dispatch to f_tag<std::true_type>
}
但是,在您的情况下,通过工厂方法和通用虚拟接口(interface),多态性可能是可行的方法。
关于c++ - 在运行时选择合适的专用模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30169433/