【发布时间】:2018-10-22 17:49:52
【问题描述】:
标题不好,但我想不出更好的。随意更改它。
这是我目前正在处理的一个模板多维数组类。我正在尽我所能优化它:
#include <array>
template <typename T, std::size_t... Dimensions>
class multidimensional_array
{
public:
using value_type = T;
using size_type = std::size_t;
private:
template<typename = void>
static constexpr size_type multiply(void)
{
return 1u;
}
template<std::size_t First, std::size_t... Other>
static constexpr size_type multiply(void)
{
return First * multidimensional_array::multiply<Other...>();
}
public:
using container_type = std::array<value_type, multidimensional_array::multiply<Dimensions...>()>;
using reference = value_type &;
using const_reference = value_type const&;
using iterator = typename container_type::iterator;
private:
container_type m_data_array;
template<typename = void>
static constexpr size_type linearise(void)
{
return 0u;
}
template<std::size_t First, std::size_t... Other>
static constexpr size_type linearise(std::size_t index, std::size_t indexes...)
{
return multidimensional_array::multiply<Other...>()*index + multidimensional_array::linearise<Other...>(indexes);
}
public:
// Constructor
explicit multidimensional_array(const_reference value = value_type {})
{
multidimensional_array::fill(value);
}
// Accessors
reference operator()(std::size_t indexes...)
{
return m_data_array[multidimensional_array::linearise<Dimensions...>(indexes)];
}
const_reference operator()(std::size_t indexes...) const
{
return m_data_array[multidimensional_array::linearise<Dimensions...>(indexes)];
}
// Iterators
iterator begin()
{
return m_data_array.begin();
}
iterator end()
{
return m_data_array.end();
}
// Other
void fill(const_reference value)
{
m_data_array.fill(value);
}
};
我的主要功能是
int main(void)
{
multidimensional_array<int, 2u, 3u, 4u, 5u, 6u> foo;
int k = 0;
for (auto& s : foo)
s = k++;
//std::cout << foo(0u, 0u, 0u, 1u, 0u) << std::endl;
return 0;
}
上述代码编译器没有警告/错误。不过,一旦我取消注释 std::cout 部分,我就会明白:
g++-7 -std=c++17 -o foo.o -c foo.cpp -Wall -Wextra -pedantic
foo.cpp: In instantiation of ‘multidimensional_array<T, Dimensions>::value_type& multidimensional_array<T, Dimensions>::operator()(std::size_t, ...) [with T = int; long unsigned int ...Dimensions = {2, 3, 4, 5, 6}; multidimensional_array<T, Dimensions>::reference = int&; multidimensional_array<T, Dimensions>::value_type = int; std::size_t = long unsigned int]’:
foo.cpp:99:37: required from here
foo.cpp:60:72: error: no matching function for call to ‘multidimensional_array<int, 2, 3, 4, 5, 6>::linearise<2, 3, 4, 5, 6>(std::size_t&)’
return m_data_array[multidimensional_array::linearise<Dimensions...>(indexes)];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
foo.cpp:38:30: note: candidate: template<class> static constexpr multidimensional_array<T, Dimensions>::size_type multidimensional_array<T, Dimensions>::linearise() [with <template-parameter-2-1> = <template-parameter-1-1>; T = int; long unsigned int ...Dimensions = {2, 3, 4, 5, 6}]
static constexpr size_type linearise(void)
^~~~~~~~~
foo.cpp:38:30: note: template argument deduction/substitution failed:
foo.cpp:60:72: error: wrong number of template arguments (5, should be at least 0)
return m_data_array[multidimensional_array::linearise<Dimensions...>(indexes)];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
foo.cpp:44:30: note: candidate: template<long unsigned int First, long unsigned int ...Other> static constexpr multidimensional_array<T, Dimensions>::size_type multidimensional_array<T, Dimensions>::linearise(std::size_t, std::size_t, ...) [with long unsigned int First = First; long unsigned int ...Other = {Other ...}; T = int; long unsigned int ...Dimensions = {2, 3, 4, 5, 6}]
static constexpr size_type linearise(std::size_t index, std::size_t indexes...)
^~~~~~~~~
foo.cpp:44:30: note: template argument deduction/substitution failed:
foo.cpp:60:72: note: candidate expects 2 arguments, 1 provided
return m_data_array[multidimensional_array::linearise<Dimensions...>(indexes)];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~
Makefile:17: recipe for target 'foo.o' failed
make: *** [foo.o] Error 1
我现在知道为什么了。我的问题是,我怎样才能修复linearise 以便它可以通过indexes 而无需通过va_list 等?不幸的是linearise已经是一个模板,可变参数函数,所以我不能在这方面使用可变参数模板恶作剧。
【问题讨论】:
-
不错的问题,但这不是minimal reproducible example - 这不是最小的。
-
@user202729 对我来说似乎是一个合理的问题。你的行为看起来像是过分热心的 SO 节制的更糟糕的问题。
-
@ArthurTacca 我怀疑
operator()及其它的 const 变体 和 swap/fill "utility" 是否有用。此外,我讨厌滚动阅读代码。 -
@Pippin 您也不需要
fill函数或构造函数。将其设为零初始化不会影响功能。
标签: c++ templates variadic-templates c++17 template-meta-programming