C++11、是否可以强制一个实例是extern,但也可以强制一个非类型模板参数的常量表达式?



Using C++11, g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)。

让我们假装我有一个模板化函数(如果它不太正确,请原谅我的术语)。

我想基于应该是"字段"的编译时实例执行"通用"算法。 唯一真正改变的是我移动到 trait 类中的这些常量(这里只添加一个,但想象一下还有更多)。 最初我声明它

constexpr field FIELD1{1};

但是在 C++11 中,非类型模板参数需要具有外部链接(不像 C++14 可以具有内部和外部链接? 因此,由于不在同一个翻译单元中,我需要使用 extern 来为其提供外部链接(对不起,如果我也破坏了该解释)。 但是通过定义它 extern,我无法使用 constexpr 来定义它,并且似乎失去该 constexpr 构造函数,此字段不再是有资格作为非类型模板参数的有效常量表达式。

有什么建议,如果有办法解决这个问题吗?对一种新的做事方法持开放态度。下面是一个简化的(不完整且非编译版本,以获取组织的要点)。

所以我看到的错误是沿着

错误:"FIELD1"的值在常量表达式中不可用

注意:"FIELD1"未声明为"constexpr" 外部常量字段字段 1; 不太确定什么是最好的选择。

我可以通过从构造函数中删除 constexpr 来摆脱第二个错误。但是我不知道如何处理常量表达式问题。

田。H

struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;

田。C

#include "field.H"
const field FIELD1{0};

field_traits。H

#include "field.H"
template< const field& T >
class fieldTraits;
template< >
class fieldTraits<FIELD1>
{
public:
// Let's say I have common field names
// with different constants that I want to plug
// into the "function_name" algorithm
static constexpr size_t field_val = 1; 
};

功能。H

#include "field.H"
template< const field& T, typename TT = fieldTraits<T> >
void function_name()
{
// Let's pretend I'm doing something useful with that data
std::cout << T.thingone << std::endl;
std::cout << TT::field_val << std::endl;
}
所以因为

不在同一个翻译单元中,我需要使用 extern 来给它外部链接(对不起,如果我也破坏了这个解释)。但是通过定义它 extern,我不能使用 constexpr 来定义它 [...]

根据我的评论,你可以。它对你不起作用,但这是一个有助于提出有效方法的步骤:

extern constexpr int i = 10;

这是完全有效的,提供了i外部链接,并使i可用于常量表达式。

但它不允许多个定义,因此它不能在包含在多个翻译单元中的头文件中工作。

通常,解决方法是inline

extern inline constexpr int i = 10;

但是变量不能在 C++11 中声明inline

除了。。。当它们不需要声明inline时,因为效果已经隐式实现:

struct S {
static constexpr int i = 10;
};

现在,S::i具有外部链接可以在常量表达式中使用!

您甚至可能不需要为此定义自己的类,具体取决于常量的类型:考虑std::integral_constant。你可以写

using i = std::integral_constant<int, 10>;

现在i::value将完全按照您的要求行事。

最新更新