对象参数的模板类专用化


template<typename T>
class A { };
U x;
A<U> ... // OK
A<x> ... // ERROR

如果可以,那么我们如何对参数是任何类型对象的类A进行专门化?

在考虑"argument是任何类型的对象";,我们应该首先理解";argument是一个对象;。(另请参阅如何使用对象实例作为模板参数?(

在此之前需要澄清:参数和自变量之间的区别是什么模板参数是定义中使用的占位符,例如此问题的<typename T>。自变量是使用定义时提供的替换项,例如此问题的<U>

对象作为模板参数

从技术上讲,既不是类型也不是模板的模板参数不能是类类型的对象,但它可以是对对象的(左值(引用C++20稍微放松了这一点,但并不是一直到";任何类型";,所以我暂时不理会这个警告

在实践中,将参数从对象转换为引用只是语法上的一点杂耍。尽管如此,这还是有一个重要的语义:不同的对象产生不同的模板实例化,即使你认为对象是";相等";。如果忽略这一点,您可能会不必要地夸大代码。你确定这与你的目标一致吗?

对象作为模板参数

既不是类型也不是模板的模板参数必须是编译时常数。这是讨论模板时经常听到的一句话。然而,在处理参考文献时,它可能有一个令人惊讶的含义。为了使对象引用成为编译时常量表达式,它必须引用具有静态存储持续时间的对象。也就是说,对象必须是:

  • 在命名空间范围内声明
  • static声明,或
  • 用CCD_ 5声明

如果你仔细想想,这应该是有意义的。引用需要它所引用的对象的地址。只有在程序开始时分配的对象具有在编译时已知的地址。函数本地对象的地址取决于特定函数调用在调用堆栈中的位置,这是一种运行时质量。

虽然模板参数可以是对任何类型的对象的引用,但任何类型的对象都不能用作相应的参数

任何类型的模板参数

受上述限制,允许任何类型的对象只是允许一个对象和允许一个类型的问题。有两件事可能会有所不同。其中一个可以隐藏在";自动;关键字。

template<const auto & Object>
class A {};

如果您想对接受哪些类型(例如类类型的对象,而不是基本类型的对象(进行更严格的限制,那么SFINAE可以使用各种类型属性。

示例:

template<const auto & Object>
class A {};
// A class for demonstration purposes
class U {};
// A global variable (declared at namespace scope)
U x;
int main()
{
// A static variable
static U y;
// A local variable
U z;
// Try to instantiate the template
A<x> compiles;
A<y> fine;
//A<z> fails;
// Suppress unused variable warnings
(void) compiles;
(void) fine;
(void) z;
}

既然你知道你可以这样做,停下来想想你是否应该。你可能不应该。也许这只是有点过于工程化了?试图成为";酷";?情况会有多糟?

最新更新