在C++中,是否可以使用定义中未使用的模板参数声明模板结构?

In C++, can I declare a template struct with a template parameter unused in the definition?

本文关键字:参数 结构 声明 定义 C++ 是否 可以使 未使用      更新时间:2023-10-16

最近我正在阅读spirit-v2-json的源代码,我对以下代码感到困惑:

template <typename Tag> struct Literal 
{ 
bool operator==(Literal const&) const { return true;  } 
bool operator< (Literal const&) const { return false; } 
};
typedef Literal<struct tag_undefined> Undefined;
typedef Literal<struct tag_null>  Null;

问题 1:Literal模板中tag参数的含义是什么?它未使用。 问题2:struct tag_undefinedstruct tag_null甚至还没有定义,为什么我们可以将它们用作模板参数?

tag参数的目的是区分不同的类型。它们不需要显示任何功能差异,但它们必须是不同的类。由于这种区分是tag参数的唯一目的,并且由于它没有在模板类本身中以任何方式使用,因此可以直接在typedef中使用不完整的原位类型。

你为什么要这样做?在上面的用例中,代码使用此模板定义两种不同的类型,UndefinedNull。他们本可以使用struct Nullstruct Undefined轻松地直接创建这些类型,但是他们将不得不分别定义运算符operator=operator<,这可能被认为是浪费。以这种方式使用类型标记可以达到与模板代码重用相同的效果。

如果你在后面的代码中查看这两种类型实际上是作为参数传递给boost::variant,这是一种"多类型,单值"的方法,用于表示变量类型的值。在这里,代码希望将UndefinedNull的概念作为这个多类型系统中的不同类型(我猜是表示未定义或空的 json 对象)。

更新:根据 OP 请求,这里有一些代码来演示在哪里可以使用和不能使用不完整的类型:

struct incomplete_struct;
struct complete_struct{};
template<typename tag>
struct some_templ
{};
template<typename tag>
struct some_other_templ
{
tag member;
};
int main()
{
some_templ<incomplete_struct> a;          //OK - incomplete template param type but not used in class so not instantiated
some_templ<struct inline_incomplete> b;   //OK - as above
some_other_templ<complete_struct> c;      //OK  - complete_struct is complete type
some_other_templ<incomplete_struct> d;    //Compile error - incomplete type, and used in template - thus instantiation of incomplete_struct is required but impossible
return 0;
} 

模板参数似乎未使用,仅用于区分类型。

是的,可以使用未定义的类型作为模板参数,只要不使用它们。模板有点像编译器支持的查找和替换,并且由于不使用模板参数,因此不会将其粘贴到代码中的任何位置。