对象参数的模板类专门化

问题描述

${project_dir}/external/lib/

如果可以的话,该如何对类template<typename T> class A { }; U x; A<U> ... // OK A<x> ... // ERROR 进行专门化处理,该类的参数是任何类型的对象?

解决方法

在考虑“参数是任何类型的对象”之前,我们应该首先了解“参数是对象”的局限性。 (另请参见How to use an object instance as template argument?

请先进行以下说明: What's the difference between an argument and a parameter? 模板参数是定义中使用的占位符,例如此问题的<typename T>。参数是使用定义时提供的替换,例如此问题的<U>

对象作为模板参数

从技术上讲,template parameter that is neither a type nor a template不能是类类型的对象,但是可以是对对象的(左值)引用。 C ++ 20 稍微放松了一下,但并非一直放松到“任何类型”,所以我暂时将忽略此警告。

在实践中,将参数从作为对象转换为作为引用只是语法上的麻烦。尽管如此,语义仍有重要意义:即使您认为对象是“相等的”,不同的对象也会产生不同的模板实例化。如果您忽略了这一点,则可能会不必要地膨胀您的代码。您确定这与您的目标一致吗?

对象作为模板参数

template argument that is neither a type nor a template必须是编译时常量。这是在讨论模板时经常听到的一种说法。但是,在处理参考文献时可能具有令人惊讶的含义。为了使对象引用成为编译时的constant expression,它必须使用static storage duration引用对象。也就是说,该对象必须是:

  • 在命名空间范围内声明,
  • static声明,或
  • extern声明。

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

虽然模板参数可以是对任何类型的对象的引用,但将任何类型的任何对象用作对应的参数并不是真的。

任何类型的模板参数

要遵守上述限制,允许任何类型的对象只是允许对象和允许类型的问题。有两件事可能会有所不同。其中之一可以隐藏在“ auto”关键字的后面。

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

如果您想更严格地接受哪些类型(例如,类类型的对象,而不是基本类型的对象),则可以将各种type propertiesSFINAE一起使用

示例:

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;
}

现在您知道自己可以做到这一点,请停止思考您是否应该。您可能不应该。也许只是过度工程?试图变得“酷”? How bad could it get?

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...