不能将类引用用作非类型模板参数

Posted

技术标签:

【中文标题】不能将类引用用作非类型模板参数【英文标题】:Can't use a class reference as a non-type template parameter 【发布时间】:2015-11-20 13:18:01 【问题描述】:

我在一个项目中,我必须使用对常量模板对象的引用作为另一个对象模板的参数。

简单地说我想这样做:

template<typename T>
class A ...

template<typename T, A<T>& a>
class B ...

int main()
   const A<int> a;
   B<int, a> b;

问题是我不知道如何实现它,我需要你的帮助。

在 Visual Studio 上,上述代码会产生以下错误:“C2971: a variable with non-static storage duration cannot be used as a non-type argument”

如果我尝试使用 constexpr 而不是 const,则进行以下更改:

constexpr A<int> &a = A<int>(3);
B<int,a> b;

我收到以下错误“C2131:表达式未计算为常量”

好吧,我确实尝试了一些我在其他帖子上看到的类似问题的东西,但不幸的是没有找到任何可以解决我的问题的东西。

我肯定做错了什么,但不知道是什么。

提前感谢您的帮助!

编辑:我尝试了答案,但不幸的是,即使一开始似乎没问题,我在编译时遇到了这个错误:C2970:涉及具有内部链接的对象的表达式不能用作非类型参数。这似乎表明我不能在另一个文件中使用模板参数? (我将所有类分开在不同的 hpp 中)有什么想法吗?

已解决:为了解决问题,我使用了下面的解决方案,并且(我假设因为我的课程在单独的 hpp 文件中)只需将关键字 extern 放在它之前:

extern const A<int> a;
int main() B<int, a> b; 

它就像一个魅力。

【问题讨论】:

相关how to initialize a constexpr reference 这毫无意义。模板参数不能作为参考。 安德鲁:不幸的是,它是项目强加的,所以它必须是模板的参数 @HolyBlackCat 可以,但是对于具有静态生命周期的对象。 @Quentin 哎呀,我没想到这是可能的。 【参考方案1】:

您不能使用局部变量作为模板的参数 - 类型定义不能本地化,它可以在局部变量范围之外使用。但是,如果您将模板参数替换为引用可以工作的全局变量:

template<typename T>
class A 
  public:
    A() 
;

template<typename T, A<T>& a>
class B 
  public:
    B() 
;

A<int> a;
int main()
  B<int, a> b;

【讨论】:

OP 使用的是非静态变量,所以这个答案不包括 OPs 问题。 这就是为什么 VS 说它是错误的 - 解决方案是不使用局部变量 没有任何解释,这只是一个代码答案,因此很差。 感谢您的回答安德烈。有没有可能找到保持 A a; 的解决方案?在主里面? 所以a 现在有静态存储持续时间,现在问题是让a 成为非本地的。

以上是关于不能将类引用用作非类型模板参数的主要内容,如果未能解决你的问题,请参考以下文章

我可以将 C++17 无捕获 lambda constexpr 转换运算符的结果用作函数指针模板非类型参数吗?

非类型模板参数

非类型模板参数的计算结果为 -1,不能缩小为类型 'unsigned long long' xcode 4.6

构造函数、模板和非类型参数

是否可以将类用作自己方法的返回类型

“类型 T 必须是引用类型才能将其用作参数”是啥意思?