问题描述
我在初始化提升直方图轴时遇到了一些麻烦。以下似乎导致数组类型和迭代器与指向第一个元素的指针之间不匹配。和见解/建议将不胜感激。谢谢。
#include <iostream>
#include <array>
#include <boost/histogram/axis.hpp>
template<class C,const C& array_>
class Foo {
protected:
typedef boost::histogram::axis::variable<> VaxisType;
inline static VaxisType axis_{array_};
std::array<unsigned char,array_.size()> bins_;
public:
Foo() { }
};
template<class C,const C& array_>
class Bar : public Foo<C,array_> {
public:
using Base_Type = Foo<C,array_>;
Bar() : Base_Type{} { }
auto idx(double x) { return Base_Type::axis_.index(x); }
};
template<class Base = float>
class FS {
private:
static const unsigned nbins = 3;
typedef std::array<double,nbins> AType;
static constexpr AType bdrs{2.0,3.0,4.0};
Bar<AType,bdrs> blah;
public:
FS() : blah{} { }
auto idx(double x) { return blah.idx(x); }
};
int
main()
{
FS x1;
std::cout << x1.idx(3.5) << "\n";
return 0;
}
生成的错误信息很长(因为尝试模板匹配),但其本质如下:
% g++ -std=c++17 -o boost_no_workie-2{,.cc}
In file included from /usr/include/boost/histogram/axis.hpp:13,from boost_no_workie-2.cc:4:
/usr/include/boost/histogram/axis/variable.hpp: In instantiation of ‘boost::histogram::axis::variable<Value,MetaData,Options,Allocator>::variable(It,It,boost::histogram::axis::variable<Value,Allocator>::metadata_type,Allocator>::allocator_type) [with It = const std::array<double,3>*; <template-parameter-2-2> = boost::histogram::detail::requires_iterator<const std::array<double,3>*,void>; Value = double; MetaData = boost::use_default; Options = boost::use_default; Allocator = std::allocator<double>; boost::histogram::axis::variable<Value,Allocator>::metadata_type = std::__cxx11::basic_string<char>; boost::histogram::axis::variable<Value,Allocator>::allocator_type = std::allocator<double>]’:
/usr/include/boost/histogram/axis/variable.hpp:122:77: required from ‘boost::histogram::axis::variable<Value,Allocator>::variable(std::initializer_list<_Up>,Allocator>::allocator_type) [with U = std::array<double,3>; Value = double; MetaData = boost::use_default; Options = boost::use_default; Allocator = std::allocator<double>; boost::histogram::axis::variable<Value,Allocator>::allocator_type = std::allocator<double>]’
boost_no_workie-2.cc:10:28: required from ‘Foo<std::array<double,3>,FS<float>::bdrs>::VaxisType Foo<std::array<double,FS<float>::bdrs>::axis_’
boost_no_workie-2.cc:22:47: required from ‘auto Bar<C,array_>::idx(double) [with C = std::array<double,3>; const C& array_ = FS<float>::bdrs]’
boost_no_workie-2.cc:34:40: required from ‘auto FS<Base>::idx(double) [with Base = float]’
boost_no_workie-2.cc:41:25: required from here
/usr/include/boost/histogram/axis/variable.hpp:95:18: error: no match for ‘operator<=’ (operand types are ‘const std::array<double,3>’ and ‘__gnu_cxx::__alloc_traits<std::allocator<double>,double>::value_type’ {aka ‘double’})
95 | if (*begin <= v.back())
... skip ...
/usr/include/boost/histogram/axis/variable.hpp:93:5: required from ‘boost::histogram::axis::variable<Value,Allocator>::allocator_type = std::allocator<double>]’
/usr/include/boost/histogram/axis/variable.hpp:122:77: required from ‘boost::histogram::axis::variable<Value,3>; const C& array_ = FS<float>::bdrs]’
boost_no_workie-2.cc:34:40: required from ‘auto FS<Base>::idx(double) [with Base = float]’
boost_no_workie-2.cc:41:25: required from here
/usr/include/c++/9/ext/new_allocator.h:145:20: error: cannot convert ‘const std::array<double,3>’ to ‘double’ in initialization
145 | noexcept(noexcept(::new((void *)__p)
| ^~~~~~~~~~~~~~~~~~
146 | _Up(std::forward<_Args>(__args)...)))
解决方法
有趣。编译你的示例给了我 GCC 10 上的 ICE(这总是一个编译器错误)。
我开始减少直到它编译。我使用了 c++17 auto non-type template arguments for simplicity:
#include <array>
#include <fmt/ranges.h>
template <auto const& array_> struct Foo {
static constexpr int N = array_.size();
};
template <auto const& array_> struct Bar : Foo<array_> {
using Base_Type = Foo<array_>;
};
struct FS {
static const unsigned nbins = 3;
static constexpr std::array<double,nbins> bdrs{2.0,3.0,4.0};
Bar<bdrs> blah;
};
int main() {
FS x1;
fmt::print(FMT_STRING("{}: {}\n"),x1.blah.N,x1.bdrs);
}
印刷品
3: {2.0,4.0}
(具有预期的出色代码生成)。
也许我们可以从这里开始,找到问题重新引入的地方。 (处理完家庭事务后会回来)。
更新:
-
跳闸的是 FS 上的模板:
-
我认为这可能是模板参数推导,但事实并非如此。
还有 ICES:https://godbolt.org/z/hxMWPj
总而言之,我认为这应该报告。如果您选择报告,CC 主干会提供更多信息:https://godbolt.org/z/489a5z - 还可以考虑使用 Creduce 进一步最小化
解决方法
有趣的是,当您在 FS 上使用模板参数时,事情会变得不那么顺畅。 (这让我有一种预感,它仍然涉及论证演绎机制)。
修正:https://godbolt.org/z/TWsas6
template <typename F>
struct FS {
static const unsigned nbins = 3;
static constexpr std::array<F,4.0};
Bar<bdrs> blah;
};
int main() {
FS<float> x1;
fmt::print(FMT_STRING("{}: {}\n"),x1.bdrs);
}
替换回您的原始样本会导致不同的编译错误,这似乎是“正常”的 Boost Histogram 类型错误,因此我将其留给您:
https://godbolt.org/z/9Tx3n3(来自您的确切代码的相同错误,只有关键更改:https://godbolt.org/z/sMMcWT