C++注意事项:数组初始化有一个很好的列表初始化列表.我有一个
int array[100] = {-1};
Run Code Online (Sandbox Code Playgroud)
期望它充满-1,但它不是,只有第一个值,其余的是0与随机值混合.
代码
int array[100] = {0};
Run Code Online (Sandbox Code Playgroud)
工作正常,并将每个元素设置为0.
我在这里想念的是什么..如果值不为零,不能初始化它吗?
2:默认初始化(如上所述)是否比通过整个数组的通常循环更快并分配一个值还是做同样的事情?
假设我有一些constexpr函数f:
constexpr int f(int x) { ... }
Run Code Online (Sandbox Code Playgroud)
我在编译时知道一些const int N:
或
#define N ...;
Run Code Online (Sandbox Code Playgroud)
要么
const int N = ...;
Run Code Online (Sandbox Code Playgroud)
根据你的答案需要.
我想要一个int数组X:
int X[N] = { f(0), f(1), f(2), ..., f(N-1) }
Run Code Online (Sandbox Code Playgroud)
这样在编译时评估函数,X中的条目由编译器计算,结果放在我的应用程序映像的静态区域,就像我在X初始化列表中使用整数文字一样.
有什么方法可以写这个吗?(例如,使用模板或宏等)
我有最好的:(感谢Flexo)
#include <iostream>
#include <array>
using namespace std;
constexpr int N = 10;
constexpr int f(int x) { return x*2; }
typedef array<int, N> A;
template<int... i> constexpr A fs() { return A{{ f(i)... }}; }
template<int...> struct S;
template<int... i> struct S<0,i...>
{ static …Run Code Online (Sandbox Code Playgroud) stackoverflow上有一个答案(我似乎无法再找到它),它演示了如何在C++ 11中使用可变参数模板在编译时创建静态数组:
template <class T, T... args>
struct array_
{
static const T data[sizeof...(args)];
};
template <class T, T... args>
const T array_<T, args...>::data[sizeof...(args)] = { args... };
Run Code Online (Sandbox Code Playgroud)
可以提供递归元函数以array_使用任意数量的参数进行实例化,然后将这些参数在编译时复制到内部数组中.这是创建元函数以在编译时生成常量数组的有用方法.
但是,一个问题是它依赖于类模板参数来获取填充数组的实际值.这导致一个主要限制:只有积分常数可以用作值模板参数.因此,您无法使用此技术生成自定义类型的数组.
我试着想办法解决这个限制,但不能提出任何建议.有没有办法让这种技术适用于非积分常数?
假设我有一个类X,哪个功能需要很多常量表值,比如一个数组A[1024].我有一个f计算其值的重复函数,就像
A[x] = f(A[x - 1]);
Run Code Online (Sandbox Code Playgroud)
假设这A[0]是一个已知常量,因此数组的其余部分也是常量.使用现代C++的功能预先计算这些值的最佳方法是什么,并且没有使用此数组的硬编码值存储文件?我的解决方法是一个const静态虚拟变量:
const bool X::dummy = X::SetupTables();
bool X::SetupTables() {
A[0] = 1;
for (size_t i = 1; i <= A.size(); ++i)
A[i] = f(A[i - 1]);
}
Run Code Online (Sandbox Code Playgroud)
但我相信,这不是最美好的方式.注意:我强调数组相当大,我想避免代码的怪异.
我目前正致力于基于模板元编程的浮点运算实现.表示编译时浮点值的模板如下:
template<bool S , std::int16_t E , std::uint64_t M>
struct number{};
Run Code Online (Sandbox Code Playgroud)
由于使用硬编码的尾数,指数等初始化这些值是一个麻烦且容易出错的过程,我编写了一个模板,用于将十进制值转换为浮点值:
template<std::int64_t INT , std::uint64_t DECS>
struct decimal{};
Run Code Online (Sandbox Code Playgroud)
其中第一个参数表示积分部分,第二个参数表示小数位数.我认为这是一种常见且众所周知的方式.
然而,这种模式会遇到一些问题(如何输入负数小于一的数字?),其中最令我讨厌的事实之一就是没有办法在逗号之后输入零数字,即数字之类的0.00032.
我是C++ 11意识到的,我正在思考一个用户定义的文字+ decltype()方法(即使有一个宏#define FLOAT(x) decltype(x_MY_LITERAL)),但我不确定这种方法在所有情境中是否可行,我的意思是,如果文字+ decltype可在模板参数的上下文中进行评估.
即使这可行,我想知道是否有其他可能的方法来解决这个问题.那么,在编译时通过tmp进行浮点式初始化有哪些替代方案呢?
仅仅为了完整性,我将描述我已经实施的替代方案,它们如何工作,以及它的功能和优点.问题本身仍然是开放的,允许任何人添加更多的替代品.
首先,我将描述我使用过的功能,以确保每个人都能理解代码.
我的图书馆,Turbo Metaprogramming Library,基于三个原则:
仅键入模板参数:完全通用的混合类型参数,值参数和模板模板参数非常难(几乎不可能),因此此库仅使用类型参数.无论何时需要使用值或模板,库都提供包装器以通过装箱传递这些参数.
统一表达式评估:在编程语言中工作时的首要需求之一是评估表达式并获取其价值的方法.Turbo提供tml::eval元函数,它接受任何类型的表达式并返回(计算)其值.
通过模板专业化定制的通用算法和元函数:每当我可以使用C++ 11模板别名来避免繁琐的typename ::type构造.我的惯例是在嵌套命名空间上定义实现模板(真正完成工作的元函数)impl,并在当前命名空间上定义结果的C++ 11模板别名.由于这些别名直接返回结果,因此它们无法在复杂表达式上进行求值(考虑元函数瞬时add<X,Y>,其中X和Y是lambda的变量.如果add是结果的别名,则不起作用,因为评估没有意义.如果我们需要表达式(元函数)而不是直接的结果,我的惯例是在func嵌套命名空间上为元函数添加别名.
这里有些例子:
using bits = tml::util::sizeof_bits<int>; //bits is a size_t integral …Run Code Online (Sandbox Code Playgroud) c++ floating-point templates template-meta-programming c++11
我想做这样的事情:
template<int N>
char* foo() {
// return a compile-time string containing N, equivalent to doing
// ostringstream ostr;
// ostr << N;
// return ostr.str().c_str();
}
Run Code Online (Sandbox Code Playgroud)
似乎boost MPL库可能允许这样但我无法弄清楚如何使用它来实现这一点.这可能吗?
我有一个全局数组,它由枚举的值索引,其中有一个元素表示值的数量.必须通过特殊值初始化数组,遗憾的是,该值不是0.
enum {
A, B, C, COUNT
};
extern const int arr[COUNT];
Run Code Online (Sandbox Code Playgroud)
在.cpp文件中:
const int arr[COUNT] = { -1, -1, -1 };
Run Code Online (Sandbox Code Playgroud)
偶尔会更改枚举:添加新值,删除一些值.我刚刚修复的代码中的错误是初始化值不足,导致数组的其余部分用零初始化.我想对这种错误采取保护措施.
问题是要么保证arr始终使用特殊值(-1在示例中)完全初始化,要么打破编译以引起开发人员注意,因此可以手动更新数组.
最近的C++标准不可用(旧的ms编译器和一些专有的垃圾).可以在一定程度上使用模板.强烈禁止STL和Boost(不要问),但我不介意复制或重新实现所需的部分.
如果事实证明是不可能的,我将不得不考虑将特殊值更改为0,但我想避免这种情况:特殊值(the -1)可能有点过于特殊,并且在其余代码中隐式编码.
我想避免DSL和代码生成:主要构建系统在ms窗口上堵塞,并且它是主要的PITA来获取在那里生成的任何东西.
我想知道是否可以使用constexpr函数初始化整个数组(使用C++ 2011).在这里,我有一些东西来说明我想做的事情:
template<unsigned int DIM> const unsigned int MyClass<DIM>::_myVar[2][3] = {
{metaFunction(0, 0, DIM), metaFunction(0, 1, DIM), metaFunction(0, 2, DIM)},
{metaFunction(1, 0, DIM), metaFunction(1, 1, DIM), metaFunction(1, 2, DIM)}
};
template<unsigned int DIM> inline constexpr unsigned int MyClass<DIM>::metaFunction(const unsigned int k, const unsigned int n, const unsigned int dim)
{
return (((n < dim) && (k < n)) ? (1<<(n-k)) : (0));
}
Run Code Online (Sandbox Code Playgroud)
有没有办法用constexpr初始化myVar而无需手动填充数组.如果存在,给定示例的语法是什么?
为了精确地解决这个问题,我搜索了一种使用单个函数调用来填充myVar的所有值的方法.
可能重复:
在C++编译时以编程方式创建静态数组
是否可以在编译时初始化以下数组?
template<int n> void
foo()
{
static int pairs[2*n]; // = {0,0, 1,1, ..., n-1,n-1}
for (int i = 0; i < n; i++)
{
pairs[2*i] = pairs[2*i+1] = i;
}
do_something_with_pairs(pairs);
}
Run Code Online (Sandbox Code Playgroud)
(我在Xcode 4.5上使用Clang,所以C++ 11可以)
可能重复:
在C++编译时以编程方式创建静态数组
我有很多数据存储在固定数组中,其元素取决于位置.可以在编译时计算每个元素的值.
我的代码几乎就像:
int fun(int p) // maybe constexpr
{
return 0x1<<p;
}
int a[17] = {
repeat_fun_from_0_to_16();
};
Run Code Online (Sandbox Code Playgroud)
因为所有的值都可以在编译时确定,所以应该有办法做到这一点,我想.
我还检查了repeat()boost.assignment中有一个,但不知道如何在这种情况下使用它.