我在使用TypeLists或模板列表时遇到了一些麻烦。那就是:
class nulltype{};
template <typename HEAD, typename TAIL>
struct tlist
{
typedef HEAD head;
typedef TAIL tail;
};
template <class TList>
class OutputClass
{
public:
void output(Type t)
{
std::cout << t << endl;
}
};
typedef tlist<double,tlist<float,NullType> > floatingPoints;
typedef tlist<std::string,tlist<char *,NullType> > text;
int main()
{
OutputClass<floatingPoints> floats = OutputClass<floatingPoints>();
floats.output(1.0f);
OutputClass<text> strings = OutputClass<text>();
floats.output("hello");
return 0;
}
基本上我的目标是我希望OutputClass.output输出传递给它的参数,但前提是该类实例typelist包含传递给函数的类型。即。参考上面的代码:浮点数只能输出其类型列表“floatingPoints”定义的float类型和double类型。如果传入一个字符串或int,我希望它会出错。
我有一段时间试图找到有关如何执行此操作的任何示例,我已经找到了一百万次的索引示例和长度示例,并且他们帮助了我很多,但我只是可以似乎没想到最后一点了。任何和所有帮助将不胜感激。
答案 0 :(得分:3)
我们首先需要一些辅助模板。第一个检查两种类型是否相同:
template <typename T, typename U>
struct is_same
{
// Default case: T and U are not the same type
static const bool value = false;
};
template <typename T>
struct is_same<T, T>
{
// Specialization: both template arguments are of the same type
static const bool value = true;
};
我们现在可以使用布尔值is_same<T, U>::value
来确定类型T
和U
是否相同。
使用is_same
我们现在可以编写一个模板来检查类型列表中是否出现特定类型:
template <typename TList, typename T>
struct contains
{
static const bool value =
is_same<typename TList::head, T>::value // Base case
|| contains<typename TList::tail, T>::value; // Recursion
};
template <typename T>
struct contains<nulltype, T>
{
// Termination condition
static const bool value = false;
};
这是一个递归模板,使用nulltype
上的特化来终止递归。
我们需要的最后一个帮助模板是enable_if
:
template <bool Cond, typename T=void>
struct enable_if
{
// Default case: Cond assumed to be false, no typedef
};
template <typename T>
struct enable_if<true, T>
{
// Specialization: Cond is true, so typedef
typedef T type;
};
enable_if<true, T>::type
产生T
,而enable_if<false, T>::type
未定义。我们利用SFINAE规则启用或禁用函数,具体取决于其模板参数,如下所示:
template <typename TList>
class OutputClass
{
public:
// Only enable the function if T is in TList (by SFINAE)
template <typename T>
typename enable_if<contains<TList, T>::value>::type
output(T t)
{
std::cout << t << std::endl;
}
};
相当一次旅行,但如果您了解所有这些,那么您就可以掌握模板元编程。有关模板元编程的深入讨论,我建议您选取C++ Template Metaprogramming(ISBN-13:9780321227256)的副本。