Here is the code:
#include <Eigen/Dense>
using namespace Eigen;
enum { TWO = 2};
Matrix<float, Dynamic, TWO> m1(42, 2); // good...
Matrix<float, Dynamic, TWO> m2(42, int(TWO)); // good...
Matrix<float, Dynamic, TWO> m3(42, TWO); // error!
When I compile the declaration of m3 is raising an error as if the enum value TWO is a floating point number:
$ g++ -I/usr/include/eigen3 -c bug.cpp
In file included from /usr/include/eigen3/Eigen/Core:366,
from /usr/include/eigen3/Eigen/Dense:1,
from bug.cpp:1:
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h: In instantiation of ‘void Eigen::PlainObjectBase<Derived>::_init2(Eigen::Index, Eigen::Index, typename Eigen::internal::enable_if<(typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime != 2), T0>::type*) [with T0 = int; T1 = <unnamed enum>; Derived = Eigen::Matrix<float, -1, 2>; Eigen::Index = long int; typename Eigen::internal::enable_if<(typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime != 2), T0>::type = int]’:
/usr/include/eigen3/Eigen/src/Core/Matrix.h:302:35: required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T0&, const T1&) [with T0 = int; T1 = <unnamed enum>; _Scalar = float; int _Rows = -1; int _Cols = 2; int _Options = 0; int _MaxRows = -1; int _MaxCols = 2]’
bug.cpp:6:39: required from here
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:740:58: error: static assertion failed: FLOATING_POINT_ARGUMENT_PASSED__INTEGER_WAS_EXPECTED
740 | EIGEN_STATIC_ASSERT(bool(NumTraits<T0>::IsInteger) &&
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
741 | bool(NumTraits<T1>::IsInteger),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/eigen3/Eigen/src/Core/util/StaticAssert.h:33:54: note: in definition of macro ‘EIGEN_STATIC_ASSERT’
33 | #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG);
|
The error message is just not chosen well since it always mentions floating points as causing the issue, but the point is that you need to pass an integer type, which an enumeration type is not.
However, with Eigen version 3.3.8 this has been changed and an enumeration type is now accepted as well and will be converted to its underlying integer type, see this issue resulting in this commit. Since that version your code compiles fine, see https://godbolt.org/z/W4jYbKfns.
Related
The following code compiles fine, with no warnings/errors:
#include <bitset>
#include <Eigen/Core>
using Array = Eigen::Array<float, -1, 1, 0, 3, 1>;
struct Tree {
Array array;
std::bitset<8> bitset;
};
auto func(Tree* tree) {
int c = tree->array.rows();
int d = tree->bitset.count();
//assert(c==d);
Array e(c);
for (int k = 0; k < d; ++k) e(k) = k;
return e.sum() / (e + 1);
}
int main() {
Tree tree;
func(&tree);
return 0;
}
Compilation cmd:
g++ -O3 -Wall -I anaconda3/envs/dev/include/eigen3/ test.cpp
However, when I uncomment the assert(), I get a maybe-uninitialized warning:
In file included from anaconda3/envs/dev/include/eigen3/Eigen/Core:253,
from test.cpp:2:
In member function ‘Eigen::internal::scalar_sum_op<LhsScalar, RhsScalar>::result_type Eigen::internal::scalar_sum_op<LhsScalar, RhsScalar>::operator()(const LhsScalar&, const RhsScalar&) const [with LhsScalar = float; RhsScalar = float]’,
inlined from ‘static Eigen::internal::redux_impl<Func, Evaluator, 3, 0>::Scalar Eigen::internal::redux_impl<Func, Evaluator, 3, 0>::run(const Evaluator&, const Func&, const XprType&) [with XprType = Eigen::Array<float, -1, 1, 0, 3, 1>; Func = Eigen::internal::scalar_sum_op<float, float>; Evaluator = Eigen::internal::redux_evaluator<Eigen::Array<float, -1, 1, 0, 3, 1> >]’ at anaconda3/envs/dev/include/eigen3/Eigen/src/Core/Redux.h:278:19,
inlined from ‘typename Eigen::internal::traits<T>::Scalar Eigen::DenseBase<Derived>::redux(const Func&) const [with BinaryOp = Eigen::internal::scalar_sum_op<float, float>; Derived = Eigen::Array<float, -1, 1, 0, 3, 1>]’ at anaconda3/envs/dev/include/eigen3/Eigen/src/Core/Redux.h:418:56,
inlined from ‘typename Eigen::internal::traits<T>::Scalar Eigen::DenseBase<Derived>::sum() const [with Derived = Eigen::Array<float, -1, 1, 0, 3, 1>]’ at anaconda3/envs/dev/include/eigen3/Eigen/src/Core/Redux.h:463:25,
inlined from ‘auto func(Tree*)’ at test.cpp:17:15:
anaconda3/envs/dev/include/eigen3/Eigen/src/Core/functors/BinaryFunctors.h:42:122: warning: ‘((const float*)((char*)&e + offsetof(Eigen::Array, Eigen::Array<float, -1, 1, 0, 3, 1>::<unnamed>.Eigen::PlainObjectBase<Eigen::Array<float, -1, 1, 0, 3, 1> >::m_storage)))[3]’ may be used uninitialized [-Wmaybe-uninitialized]
42 | EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE result_type operator() (const LhsScalar& a, const RhsScalar& b) const { return a + b; }
| ~~^~~
test.cpp: In function ‘auto func(Tree*)’:
test.cpp:15:9: note: ‘e’ declared here
15 | Array e(c);
| ^
My question is this: why does the presence of the assert() affect whether or not gcc reports a maybe-uninitialized warning?
The example I show happens to use the eigen3 library, but I think my question is more general. How can the inclusion of an assert() that merely compares two int values lead to a compiler warning like this?
I want to note that this code is a minimal reproducible example for this assert-dependent-warning behavior. Removing the for-loop inside func(), for instance, makes the warning appear even without the assert. Replacing e.sum() / (e + 1) with a simpler expression like e + 1 makes the warning disappear with the assert. Replacing the std::bitset with something else also makes the warning disappear with the assert.
I am using gcc-11.3.0 and eigen-3.4.0.
This is apparently due to a gcc bug. The bug is present in gcc-12 or lower, and is fixed in gcc-13. A fix might be coming in gcc-12.
Bug report: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108230
I am trying to make a custom Vector3 inheriting from Eigen's vector 3 like so.
using Vector3 = Eigen::Vector3d;
enum class CustomEnum
{
E1, E2 E3, E4,
};
class CustomVector3 : public Vector3
{
public:
// Taken from here: https://eigen.tuxfamily.org/dox/TopicCustomizing_InheritingMatrix.html
CustomVector3():Vector3(){}
template<typename OtherDerived>
CustomVector3(const Eigen::MatrixBase<OtherDerived>& other) : Vector3(other) {}
// Initializer Constructor
template<typename OtherDerived>
CustomVector3(const std::initializer_list<OtherDerived>& other) : Vector3(other) {}
template<typename OtherDerived>
CustomVector3& operator=(const Eigen::MatrixBase<OtherDerived>& other){
this->Vector3::operator=(other);
return *this;
}
CustomEnum e = CustomEnum::E1;
};
And the goal is to do the following:
TEST_CASE("Initalizer List Test")
{
CustomVector3 vec = {1.1, 2.2, 3.3};
CHECK(vec.x() == 1.1);
CHECK(vec.y() == 2.2);
CHECK(vec.z() == 3.3);
assert(vec.frame == CustomEnum::E1);
}
Without the initializer constructor, I am able to do the following, but not my goal mentioned above:
Vector3 data = {1.1, 2.2, 3.3};
CustomVector3 framedData = data;
With the initializer constructor, I get the following compile error message (I called it FramedVector3 in my code, but for clarity I called it CustomVector3 in this post):
/usr/include/eigen3/Eigen/src/Core/Matrix.h: In instantiation of ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T&) [with T = std::initializer_list<double>; _Scalar = double; int _Rows = 3; int _Cols = 1; int _Options = 0; int _MaxRows = 3; int _MaxCols = 1]’:
/home/seedship/uavAP/include/uavAP/Core/FramedVector3.h:23:81: required from ‘FramedVector3::FramedVector3(const std::initializer_list<_Tp>&) [with OtherDerived = double]’
/home/seedship/uavAP/include/uavAP/Core/SensorData.h:128:38: required from here
/usr/include/eigen3/Eigen/src/Core/Matrix.h:294:31: error: no matching function for call to ‘Eigen::Matrix<double, 3, 1>::_init1<std::initializer_list<double> >(const std::initializer_list<double>&)’
294 | Base::template _init1<T>(x);
| ~~~~~~~~~~~~~~~~~~~~~~~~^~~
In file included from /usr/include/eigen3/Eigen/Core:462,
from /usr/include/eigen3/Eigen/Dense:1,
from /usr/local/include/cpsCore/Utilities/LinearAlgebra.h:13,
from /home/seedship/uavAP/include/uavAP/Core/FramedVector3.h:9,
from /home/seedship/uavAP/include/uavAP/Core/SensorData.h:11,
from /home/seedship/uavAP/include/uavAP/Core/Orientation/ENU.h:8,
from /home/seedship/uavAP/src/Core/Orientation/ENU.cpp:5:
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:774:30: note: candidate: ‘void Eigen::PlainObjectBase<Derived>::_init1(Eigen::Index, typename Eigen::internal::enable_if<(((typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime != 1) || (! Eigen::internal::is_convertible<T, typename Eigen::internal::traits<T>::Scalar>::value)) && ((! Eigen::internal::is_same<typename Eigen::internal::traits<T>::XprKind, Eigen::ArrayXpr>::value) || (typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime == Eigen::Dynamic))), T>::type*) [with T = std::initializer_list<double>; Derived = Eigen::Matrix<double, 3, 1>; Eigen::Index = long int; typename Eigen::internal::enable_if<(((typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime != 1) || (! Eigen::internal::is_convertible<T, typename Eigen::internal::traits<T>::Scalar>::value)) && ((! Eigen::internal::is_same<typename Eigen::internal::traits<T>::XprKind, Eigen::ArrayXpr>::value) || (typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime == Eigen::Dynamic))), T>::type = std::initializer_list<double>]’
774 | EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if< (Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value)
| ^~~~~~
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:774:43: note: no known conversion for argument 1 from ‘const std::initializer_list<double>’ to ‘Eigen::Index’ {aka ‘long int’}
774 | EIGEN_STRONG_INLINE void _init1(Index size, typename internal::enable_if< (Base::SizeAtCompileTime!=1 || !internal::is_convertible<T, Scalar>::value)
| ~~~~~~^~~~
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:788:30: note: candidate: ‘template<class T> void Eigen::PlainObjectBase<Derived>::_init1(const Scalar&, typename Eigen::internal::enable_if<((typename Eigen::internal::dense_xpr_base<Derived>::type::SizeAtCompileTime == 1) && Eigen::internal::is_convertible<T, typename Eigen::internal::traits<T>::Scalar>::value), T>::type*) [with T = T; Derived = Eigen::Matrix<double, 3, 1>]’
788 | EIGEN_STRONG_INLINE void _init1(const Scalar& val0, typename internal::enable_if<Base::SizeAtCompileTime==1 && internal::is_convertible<T, Scalar>::value,T>::type* = 0)
| ^~~~~~
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:788:30: note: template argument deduction/substitution failed:
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h: In substitution of ‘template<class T> void Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1> >::_init1<T>(const Scalar&, typename Eigen::internal::enable_if<((Eigen::MatrixBase<Eigen::Matrix<double, 3, 1> >::SizeAtCompileTime == 1) && Eigen::internal::is_convertible<T, double>::value), T>::type*) [with T = std::initializer_list<double>]’:
/usr/include/eigen3/Eigen/src/Core/Matrix.h:294:31: required from ‘Eigen::Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>::Matrix(const T&) [with T = std::initializer_list<double>; _Scalar = double; int _Rows = 3; int _Cols = 1; int _Options = 0; int _MaxRows = 3; int _MaxCols = 1]’
/home/seedship/uavAP/include/uavAP/Core/FramedVector3.h:23:81: required from ‘FramedVector3::FramedVector3(const std::initializer_list<_Tp>&) [with OtherDerived = double]’
/home/seedship/uavAP/include/uavAP/Core/SensorData.h:128:38: required from here
/usr/include/eigen3/Eigen/src/Core/PlainObjectBase.h:788:30: error: invalid use of incomplete type ‘struct Eigen::internal::enable_if<false, std::initializer_list<double> >’
[Truncated for brevity]
Can anyone explain what I am missing? I'm confused why the assignment operator works, but not the constructor. This happens on both Eigen 3.3.9-1 and eigen-git.
Update: maybe this question is very library specific, so I asked on the Eigen gitlab project (https://gitlab.com/libeigen/eigen/-/issues/2192)
You need to use an extra pair of parenthesis. Also there is no point in templating this constructor since the template argument type needs to match the scalar type of the Eigen vector and if you'd like the scalar type to be configurable you'd need to template the whole class.
In summary
CustomVector3(const std::initializer_list<double>& other) : Vector3({other}) {}
is the correct way to do this. The reason is that Eigen::Vector3d is a typedef for Eigen::Matrix<double, 3, 1>. The initializer list constructor for matrices needs to handle multiple rows and columns however and has thus the signature
explicit PlainObjectBase(const std::initializer_list<std::initializer_list<Scalar>>& list);
If you always want to use 3D vectors the (easier) alternative is to use Eigen's 3D constructor and aggregate initialization:
CustomVector3(double x, double y, double z) : Vector3(x, y, z) {}
I'm having some trouble in initializing a boost histogram axis. The following appears to cause a mismatch between the type of the array and iterator vs pointer to first element. And insights/suggestions would be appreciated. thanks.
#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;
}
The error message generated is quite long (because of attempted template matching), but the essence of it is as follows:
% 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, MetaData, Options, Allocator>::metadata_type, boost::histogram::axis::variable<Value, MetaData, Options, 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, MetaData, Options, Allocator>::metadata_type = std::__cxx11::basic_string<char>; boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::allocator_type = std::allocator<double>]’:
/usr/include/boost/histogram/axis/variable.hpp:122:77: required from ‘boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::variable(std::initializer_list<_Up>, boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::metadata_type, boost::histogram::axis::variable<Value, MetaData, Options, 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, MetaData, Options, Allocator>::metadata_type = std::__cxx11::basic_string<char>; boost::histogram::axis::variable<Value, MetaData, Options, 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, 3>, 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, MetaData, Options, Allocator>::variable(It, It, boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::metadata_type, boost::histogram::axis::variable<Value, MetaData, Options, 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, MetaData, Options, Allocator>::metadata_type = std::__cxx11::basic_string<char>; boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::allocator_type = std::allocator<double>]’
/usr/include/boost/histogram/axis/variable.hpp:122:77: required from ‘boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::variable(std::initializer_list<_Up>, boost::histogram::axis::variable<Value, MetaData, Options, Allocator>::metadata_type, boost::histogram::axis::variable<Value, MetaData, Options, 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, MetaData, Options, Allocator>::metadata_type = std::__cxx11::basic_string<char>; boost::histogram::axis::variable<Value, MetaData, Options, 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, 3>, 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/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)...)))
Interesting. Compiling your sample gave me ICE on GCC 10 (which is always a compiler bug).
I started reducing till it did compile. I used c++17 auto non-type template arguments for simplicity:
Live on Compiler Explorer
#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);
}
Prints
3: {2.0, 3.0, 4.0}
(with excellent codegen as expected).
Perhaps we can take it from here, to find where the problem is reintroduced. (Will be back after family things).
UPDATE:
It's the template on FS<> that trips:
ICES: https://godbolt.org/z/onaEor
I thought it might have been the template argument deduction, but it isn't.
Also ICES: https://godbolt.org/z/hxMWPj
All in all I think this should be reported. CC trunk gives a more info should you chose to report: https://godbolt.org/z/489a5z - also consider using Creduce to minimize further
Workaround
Interestingly things get unstuck when you use the template argument on FS. (This gives me a hunch it still involves the argument deduction machinery).
FIXED: https://godbolt.org/z/TWsas6
template <typename F>
struct FS {
static const unsigned nbins = 3;
static constexpr std::array<F, nbins> bdrs{2.0, 3.0, 4.0};
Bar<bdrs> blah;
};
int main() {
FS<float> x1;
fmt::print(FMT_STRING("{}: {}\n"), x1.blah.N, x1.bdrs);
}
Substituting back into your original sample leads to different compilation errors, which seem to be "normal" Boost Histogram type errors, so I'll leave that for you:
https://godbolt.org/z/9Tx3n3 (same error coming from your exact code with only the crucial changes: https://godbolt.org/z/sMMcWT
typedef std::array<T, 3> C;
constexpr C c = {1, 2, 3.5};
constexpr T t1 = c.at(0);`
The third line gives me an error when compiled with g++. It works fine with clang++ when LLVM libc++ is used. It seems like return of c.at(0) is not a constexpr using C++ 14. However, std::array::at is of the same return type as described here.
This is complete error message:
constexpr const value_type& std::__1::array<_Tp,
_Size>::at(std::__1::array<_Tp, _Size>::size_type) const [with _Tp =
double; long unsigned int _Size = 3ul; std::__1::array<_Tp,
_Size>::const_reference = const double&; std::__1::array<_Tp,
_Size>::value_type = double; std::__1::array<_Tp, _Size>::size_type = long
unsigned int]’
called in a constant expression
constexpr T t1 = c.at(0);
I was trying to perform image captioning with tensorflow on cpp. I was following the direction on How to import an saved Tensorflow model train using tf.estimator and predict on input data and tried
int main(int argc, char**) {
....
auto x = tf::Tensor(tf::DT_UINT8, tf::TensorShape({height, width, channel}));
auto matrix = x.matrix<char>();
....
}
When I compile the program, the code
> In file included from /usr/local/include/tensorflow/core/framework/tensor.h:26:0,
from /usr/local/include/tensorflow/core/public/session.h:23,
from /usr/local/include/tensorflow/cc/saved_model/loader.h:26,
from server.cpp:22:
/usr/local/include/tensorflow/core/framework/types.h: In instantiation of ‘struct tensorflow::DataTypeToEnum<char>’:
/usr/local/include/tensorflow/core/framework/tensor.h:530:46: required from ‘typename tensorflow::TTypes<T, NDIMS>::Tensor tensorflow::Tensor::tensor() [with T = char; long unsigned int NDIMS = 2ul; typename tensorflow::TTypes<T, NDIMS>::Tensor = Eigen::TensorMap<Eigen::Tensor<char, 2, 1, long int>, 16, Eigen::MakePointer>]’
/usr/local/include/tensorflow/core/framework/tensor.h:240:25: required from ‘typename tensorflow::TTypes<T>::Matrix tensorflow::Tensor::matrix() [with T = char; typename tensorflow::TTypes<T>::Matrix = Eigen::TensorMap<Eigen::Tensor<char, 2, 1, long int>, 16, Eigen::MakePointer>]’
server.cpp:121:34: required from here
/usr/local/include/tensorflow/core/framework/types.h:138:3: error: static assertion failed: Specified Data Type not supported
static_assert(IsValidDataType<T>::value, "Specified Data Type not supported");In file included from /usr/local/include/tensorflow/core/public/session.h:23:0,
from /usr/local/include/tensorflow/cc/saved_model/loader.h:26,
from server.cpp:22:
/usr/local/include/tensorflow/core/framework/tensor.h: In instantiation of ‘typename tensorflow::TTypes<T, NDIMS>::Tensor tensorflow::Tensor::tensor() [with T = char; long unsigned int NDIMS = 2ul; typename tensorflow::TTypes<T, NDIMS>::Tensor = Eigen::TensorMap<Eigen::Tensor<char, 2, 1, long int>, 16, Eigen::MakePointer>]’:
/usr/local/include/tensorflow/core/framework/tensor.h:240:25: required from ‘typename tensorflow::TTypes<T>::Matrix tensorflow::Tensor::matrix() [with T = char; typename tensorflow::TTypes<T>::Matrix = Eigen::TensorMap<Eigen::Tensor<char, 2, 1, long int>, 16, Eigen::MakePointer>]’
server.cpp:121:34: required from here
/usr/local/include/tensorflow/core/framework/tensor.h:530:46: error: ‘v’ is not a member of ‘tensorflow::DataTypeToEnum<char>’
CheckTypeAndIsAligned(DataTypeToEnum<T>::v());
Did anybody came across the same problem?
Found a solution. It seems like two issues were present.
(1) DT_UINT8 is uchar in c++
(2) use tensor instead of matrix
I changed the code to
auto x = tf::Tensor(tf::DT_UINT8, tf::TensorShape(
{height, width,3}));
auto matrix = x.tensor<uchar, 3>();
and worked. Got the idea from https://github.com/tensorflow/tensorflow/issues/19909
Even though you declare your TensorShape with an initialization list, you should still specify the number of dimensions of your matrix, as it cannot be deduced at compilation time in C++.
auto x = tf::Tensor(tf::DT_UINT8, tf::TensorShape({height, width, channel}));
auto matrix = x.matrix<char, 3>();