首页 > 解决方案 > 错误 C2971 具有非静态存储持续时间的变量不能用作非类型参数

问题描述

这是一个简单的例子(想法是避免函数内部出现巨大的if..elseswitch块):

namespace foo {
   enum class VALUES : int { val_0 = 0, val_1 = 1 };

   template<VALUES T>
   void print();

   template<>
   void print<VALUES::val_0>() { std::cout << "val_0\n"; }

   template<>
   void print<VALUES::val_1>() { std::cout << "val_1\n"; }

   void bar(int type) {
      VALUES v = static_cast<VALUES>(type);
      print<v>(); //error C2971 - "v" is a non-constant argument at compile-time
   }
};

问题是如何print<...>()根据bar's 参数调用?请不要建议使用if..elseor switch

标签: c++templates

解决方案


模板是在编译时推导出来的。这意味着这些模板参数是常量(在编译时)。在你的情况下,int type不是一个常量类型,所以是VALUES v. 为了v在编译时解析,您需要将其标记为constexpr VALUES v;,这也意味着您需要使用值对其进行初始化。在这种情况下,使用编译时可解析的值。这就是为什么这有效,

constexpr VALUES v = VALUES::val_0;
print<v>(); 

但不是这个,

VALUES m = VALUES::val_0;
constexpr VALUES v = m;    // As soon as you do this, it is no longer resolvable at compile time.
print<v>(); 

所以最简单的答案是,您必须使用if/或模板来完成它。elseswitch


推荐阅读