C++基于1而不是0的访问数组,方法是在编译时移位
C++ access arrays based on 1 and not 0, by shifting at compile time
我正在编写一个小型张量库(灵感来自这里:http://www.wlandry.net/Projects/FTensor(,依靠C++11或14。
为了清楚起见,我想访问从 1 开始的索引,而不是 0。例如,对于向量 v,使用 v(1(、v(2( 和 v(3( 访问存储在常规一维数组中的分量。 (编辑:这是用于连续介质力学应用。人们习惯于从 1 开始。是的,这对程序员来说是不自然的。
现在,我已经知道如何在运行时执行此操作。我想知道我们是否可以在运行时避免这种计算,因为在对称的情况下,对于高阶张量来说,它会变得更加复杂。
我找到了这种编写编译时图的方法,我手动放置移位:https://stackoverflow.com/a/16491172/1771099
但是,使用上面 SO 答案中的代码,我不能做这样的事情:
for i=1; i<4;i++){
std::cout << mymap::get<i>::val << std::endl;
}
因为我不知道编译时间。 有没有聪明的方法可以做到这一点?构建一种静态映射,对于每个张量阶数和对称性,我们可以在运行时查找?
谢谢
编辑:这是我认为"坏"的。Contexpr实际上毫无用
处// subtract 1 to an index
inline constexpr size_t
sub_1_to_idx(size_t const &i) {
return i - 1;
}
// build a parameter pack from (a,b,c,...) to (a-1,b-1,c-1,...)
template<typename... idx>
constexpr std::array<size_t, sizeof...(idx)>
shift_idx(const idx &... indices) {
return std::array<size_t, sizeof...(idx)>
{{sub_1_to_idx(indices)...}};
};
//use this to return an index of a 1D array where the values of a possibly multidimentional, possibly symmetric Tensor are stored.
template<>
template<typename... idx>
size_t
TA_Index<2, Tsym::IJ>::of(const idx&... indices) {
static_assert(sizeof...(indices) == 2, "*** ERROR *** Please access second order tensor with 2 indices");
const std::array<size_t, sizeof...(idx)> id = shift_idx(indices...);
return id[0] > id[1] ? (id[0] + (id[1] * (2 * 3 - id[1] - 1)) / 2)
: (id[1] + (id[0] * (2 * 3 - id[0] - 1)) / 2);
对此你没有什么可以改变的。是的,您可以创建一个密集的编译时查找表,但是您会从单点开始(需要填充,即空间开销(还是从零开始(需要重新索引,即时间开销(来访问它?它真的会给你带来任何有意义的表现吗?
您是否比较了由从 1 开始的索引和从 0 开始的索引生成的程序集?
https://godbolt.org/z/9pKt6Q
它们几乎相同,除了两个lea
(好吧,从两个输入指数中减去 1(和一个额外的cmova
(不知道那里发生了什么(。如果从零开始的代码足够好,那么从零开始的代码也同样好。
此外,无论哪种情况,编译器都会完美地常量折叠编译时已知的索引。这是编译器的基本优化,因此当索引在编译时已知时,您的函数是否constexpr
将是无关紧要的。
最后,对于高维/更大张量的操作,索引计算产生的半随机访问模式可能是比索引计算本身更大的性能瓶颈(由于没有有效地使用缓存(。
- 有没有一种方法可以在编译时获得作用域类名
- 访问条件类成员的方法不仅在被调用时才编译
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- C++11:模板方法的模板函数调用无法编译?
- 在编译时评估函数开销的通用方法
- VS2017 版本 15.8.3 成功编译内联方法,而不返回所需值
- 在C++中执行 N 阶乘编译时间的 3 种不同/相同方法
- unordered_set .find 方法无法编译的 C++ "expression must have class type"错误
- 如何检查在编译时是否调用了模板化方法?
- C++基于1而不是0的访问数组,方法是在编译时移位
- std::value templated 方法的函数使用 clang 和 g++ 进行编译,但不使用 msvc 进行编译
- CMake + Qt,moc 编译失败,无法实现 QMetaObject 方法(编译器找不到基本 ui 对象的标头?
- 返回实例变量的c++方法可以访问变量中的数据,但不能更改它,但在编译时不会生成错误
- 尝试编译SFINAE检查中使用的方法体时发生编译错误
- 编译错误 std::vector<std::shared_ptr<T>>迭代器和擦除方法
- 模棱两可的方法编译误差
- 使用内联方法编译简单的标头
- 为什么 boost::enable_if 不会导致重复的重载方法编译错误
- c++向量排序方法编译失败,返回预期表达式
- 模板方法编译错误,从内部类返回实例