C++11,是否可以强制一个实例是外部的,但也是一个非类型模板参数的常量表达式?
C++11, Is it possible to force an instance to be extern but also a constant expression of a non-type template parameter?
使用 C++11、g++ (GCC) 4.4.7 20120313(Red Hat 4.4.7-18)。
假设我有一个模板函数(如果我的术语不太正确,请原谅我)。
我想根据本应是 "field" 的编译时实例执行 "general" 算法。唯一真正改变的是我移入 trait 类 中的这些常量(这里只添加了一个,但可以想象还有更多)。最初我将其声明为
constexpr field FIELD1{1};
但是在 C++11 中,非类型模板参数需要有外部链接(不像 C++14 可以有内部和外部链接?)。因此,因为不在同一个翻译单元中,所以我需要使用 extern 来为其提供外部链接(抱歉,如果我也扼杀了那个解释)。但是通过将它定义为 extern,我无法使用 constexpr 来定义它,而且似乎丢失了 constexpr 构造函数,这个字段不再是一个有效的常量表达式,无法作为非类型模板参数。
如果有什么办法可以解决这个问题,有什么建议吗?接受一种新的做事方法。下面是一个简化的(不完整的、非编译版本,以获取组织的要点)。
所以我看到的错误是
错误:“FIELD1”的值在常量表达式中不可用
注意:“FIELD1”未声明为“constexpr”
外部常量字段 FIELD1;
不太确定什么是最佳选择。
我可以通过从构造函数中删除 constexpr 来消除第二个错误。但是后来我不知道如何解决常量表达式问题。
field.H
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;
field.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;
};
function.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;
}
So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using 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
有外部链接并且可用于常量表达式!
您甚至可能不需要为此定义自己的 class,具体取决于常量的类型:考虑 std::integral_constant
。你可以写
using i = std::integral_constant<int, 10>;
现在 i::value
将完全按照您的意愿进行。
使用 C++11、g++ (GCC) 4.4.7 20120313(Red Hat 4.4.7-18)。
假设我有一个模板函数(如果我的术语不太正确,请原谅我)。
我想根据本应是 "field" 的编译时实例执行 "general" 算法。唯一真正改变的是我移入 trait 类 中的这些常量(这里只添加了一个,但可以想象还有更多)。最初我将其声明为
constexpr field FIELD1{1};
但是在 C++11 中,非类型模板参数需要有外部链接(不像 C++14 可以有内部和外部链接?)。因此,因为不在同一个翻译单元中,所以我需要使用 extern 来为其提供外部链接(抱歉,如果我也扼杀了那个解释)。但是通过将它定义为 extern,我无法使用 constexpr 来定义它,而且似乎丢失了 constexpr 构造函数,这个字段不再是一个有效的常量表达式,无法作为非类型模板参数。
如果有什么办法可以解决这个问题,有什么建议吗?接受一种新的做事方法。下面是一个简化的(不完整的、非编译版本,以获取组织的要点)。
所以我看到的错误是
错误:“FIELD1”的值在常量表达式中不可用
注意:“FIELD1”未声明为“constexpr” 外部常量字段 FIELD1; 不太确定什么是最佳选择。
我可以通过从构造函数中删除 constexpr 来消除第二个错误。但是后来我不知道如何解决常量表达式问题。
field.H
struct field
{
int thingone;
constexpr field(int i):thingone(i){}
};
extern const field FIELD1;
field.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;
};
function.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;
}
So because not's in the same translation unit I needed to use extern in order to give it external linkage (sorry if I butchered that explanation also). But by defining it extern I can't define it using 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
有外部链接并且可用于常量表达式!
您甚至可能不需要为此定义自己的 class,具体取决于常量的类型:考虑 std::integral_constant
。你可以写
using i = std::integral_constant<int, 10>;
现在 i::value
将完全按照您的意愿进行。