ami-iit / matio-cpp

A C++ wrapper of the matio library, with memory ownership handling, to read and write .mat files.
https://ami-iit.github.io/matio-cpp/
BSD 2-Clause "Simplified" License
59 stars 9 forks source link

Missing deduction guides for Span object #51

Closed GiulioRomualdi closed 2 years ago

GiulioRomualdi commented 2 years ago

Accordingly to the std documentation the following code should work

std::vector<int32_t> v{2};
matioCpp::Span s{v};

However when I try to compile the code I got

home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: error: class template argument deduction failed:
   44 |         matioCpp::Span s{v};
      |                           ^
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: error: no matching function for call to ‘Span(std::vector<int>&)’
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:558:24: note: candidate: ‘template<class ElementType, long int Extent> Span(matioCpp::Span<ElementType, Extent>::KnownNotNull, matioCpp::Span<ElementType, Extent>::index_type)-> matioCpp::Span<ElementType, Extent>’
  558 |     MATIOCPP_CONSTEXPR Span(KnownNotNull ptr, index_type count) : storage_(ptr, count) {}
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:558:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   candidate expects 2 arguments, 1 provided
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:424:24: note: candidate: ‘template<class ElementType, long int Extent, class OtherElementType, long int OtherExtent, class> Span(const matioCpp::Span<OtherElementType, OtherExtent>&)-> matioCpp::Span<ElementType, Extent>’
  424 |     MATIOCPP_CONSTEXPR Span(const Span<OtherElementType, OtherExtent>& other)
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:424:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   ‘std::vector<int>’ is not derived from ‘const matioCpp::Span<OtherElementType, OtherExtent>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:416:24: note: candidate: ‘template<class ElementType, long int Extent> Span(const matioCpp::Span<ElementType, Extent>&)-> matioCpp::Span<ElementType, Extent>’
  416 |     MATIOCPP_CONSTEXPR Span(const Span& other) noexcept = default;
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:416:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   ‘std::vector<int>’ is not derived from ‘const matioCpp::Span<ElementType, Extent>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:411:24: note: candidate: ‘template<class ElementType, long int Extent, class Container, class, class> Span(const Container&)-> matioCpp::Span<ElementType, Extent>’
  411 |     MATIOCPP_CONSTEXPR Span(const Container& cont) : Span(cont.data(), static_cast<index_type>(cont.size()))
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:411:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   couldn’t deduce template parameter ‘ElementType’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:402:24: note: candidate: ‘template<class ElementType, long int Extent, class Container, class, class> Span(Container&)-> matioCpp::Span<ElementType, Extent>’
  402 |     MATIOCPP_CONSTEXPR Span(Container& cont) : Span(cont.data(), static_cast<index_type>(cont.size()))
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:402:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   couldn’t deduce template parameter ‘ElementType’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:389:24: note: candidate: ‘template<class ElementType, long int Extent, long unsigned int N> Span(const std::array<typename std::remove_const<_Tp>::type, N>&)-> matioCpp::Span<ElementType, Extent>’
  389 |     MATIOCPP_CONSTEXPR Span(const std::array<std::remove_const_t<element_type>, N>& arr) noexcept
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:389:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   ‘std::vector<int>’ is not derived from ‘const std::array<typename std::remove_const<_Tp>::type, N>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:383:24: note: candidate: ‘template<class ElementType, long int Extent, long unsigned int N, class ArrayElementType> Span(std::array<ArrayElementType, N>&)-> matioCpp::Span<ElementType, Extent>’
  383 |     MATIOCPP_CONSTEXPR Span(std::array<ArrayElementType, N>& arr) noexcept
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:383:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   ‘std::vector<int>’ is not derived from ‘std::array<ArrayElementType, N>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:377:24: note: candidate: ‘template<class ElementType, long int Extent, long unsigned int N> Span(ElementType (&)[N])-> matioCpp::Span<ElementType, Extent>’
  377 |     MATIOCPP_CONSTEXPR Span(element_type (&arr)[N]) noexcept
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:377:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   mismatched types ‘ElementType [N]’ and ‘std::vector<int>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:371:24: note: candidate: ‘template<class ElementType, long int Extent> Span(matioCpp::Span<ElementType, Extent>::pointer, matioCpp::Span<ElementType, Extent>::pointer)-> matioCpp::Span<ElementType, Extent>’
  371 |     MATIOCPP_CONSTEXPR Span(pointer firstElem, pointer lastElem)
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:371:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   mismatched types ‘matioCpp::Span<ElementType, Extent>::element_type*’ and ‘std::vector<int>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:369:24: note: candidate: ‘template<class ElementType, long int Extent> Span(matioCpp::Span<ElementType, Extent>::pointer, matioCpp::Span<ElementType, Extent>::index_type)-> matioCpp::Span<ElementType, Extent>’
  369 |     MATIOCPP_CONSTEXPR Span(pointer ptr, index_type count) : storage_(ptr, count) {}
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:369:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   mismatched types ‘matioCpp::Span<ElementType, Extent>::element_type*’ and ‘std::vector<int>’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:364:24: note: candidate: ‘template<class ElementType, long int Extent, bool Dependent, class> Span()-> matioCpp::Span<ElementType, Extent>’
  364 |     MATIOCPP_CONSTEXPR Span() noexcept : storage_(nullptr, details::extent_type<0>())
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:364:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   candidate expects 0 arguments, 1 provided
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:30,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/ForwardDeclarations.h:176:7: note: candidate: ‘template<class ElementType, long int Extent> Span(matioCpp::Span<ElementType, Extent>)-> matioCpp::Span<ElementType, Extent>’
  176 | class Span;
      |       ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/ForwardDeclarations.h:176:7: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   ‘std::vector<int>’ is not derived from ‘matioCpp::Span<ElementType, Extent>’
   44 |         matioCpp::Span s{v};

In this case the used deduction guides used should be:

template<class R>
span(R&&) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>>;
GiulioRomualdi commented 2 years ago

with this

std::vector<int32_t> v{2};
matioCpp::Span<int32_t> s{v};

everything works fine

It is nice to have this deduction guide since it will allow to write the following code

void foo(Span<int> s);

std::vector<int> v{1};
foo(v);

right now what we should do is

void foo(Span<int> s);

std::vector<int> v{1};
foo(make_span(v));

Notice that make_span is not defined by the standard

S-Dafarra commented 2 years ago

Yes, the relevant error is

In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:411:24: note: candidate: ‘template<class ElementType, long int Extent, class Container, class, class> Span(const Container&)-> matioCpp::Span<ElementType, Extent>’
  411 |     MATIOCPP_CONSTEXPR Span(const Container& cont) : Span(cont.data(), static_cast<index_type>(cont.size()))
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:411:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   couldn’t deduce template parameter ‘ElementType’
   44 |         matioCpp::Span s{v};
      |                           ^
In file included from /home/gromualdi/robot-code/yarp-telemetry/src/libYARP_telemetry/src/yarp/telemetry/experimental/Record.h:12,
                 from /home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:14:
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:402:24: note: candidate: ‘template<class ElementType, long int Extent, class Container, class, class> Span(Container&)-> matioCpp::Span<ElementType, Extent>’
  402 |     MATIOCPP_CONSTEXPR Span(Container& cont) : Span(cont.data(), static_cast<index_type>(cont.size()))
      |                        ^~~~
/home/gromualdi/robot-code/robotology-superbuild/build/install/include/matioCpp/Span.h:402:24: note:   template argument deduction/substitution failed:
/home/gromualdi/robot-code/yarp-telemetry/src/examples/circular_buffer_record_example.cpp:44:27: note:   couldn’t deduce template parameter ‘ElementType’

As you noticed, it fails to deduce the ElementType.

I am not sure I understood what you meant in

In this case the used deduction guides used should be:

template<class R>
span(R&&) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>>;
GiulioRomualdi commented 2 years ago

I am not sure I understood what you meant in

In this case the used deduction guides used should be:

template<class R>
span(R&&) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>>;

Accordingly to what is written here the deduction guide used for std::vector is image

image

S-Dafarra commented 2 years ago
std::ranges::range_reference_t

Ah I see. The problem is that std::ranges is C++20 (https://en.cppreference.com/w/cpp/ranges)

GiulioRomualdi commented 2 years ago

This implementation seems able to perform the deduction. https://github.com/martinmoene/span-lite

What do you think to port it matio-cpp?

GiulioRomualdi commented 2 years ago

Before taking any decision let me try in a toy problem 😃

GiulioRomualdi commented 2 years ago

The following code works with span-line

#include "nonstd/span.hpp"
#include <array>
#include <vector>
#include <iostream>

std::ptrdiff_t size( nonstd::span<const int> spn )
{
    return spn.size();
}

int main()
{
    int arr[] = { 1, };

    std::cout <<
        "C-array:" << size( arr ) <<
        " array:"  << size( std::array <int, 2>{ 1, 2, } ) <<
        " vector:" << size( std::vector<int   >{ 1, 2, 3, } );
}
S-Dafarra commented 2 years ago

I would say that before moving to a completely new implementation, I would like to understand if it is possible to fix the current implementation.

Moving to a new implementation of span might be potentially a lot of work (also for those applications depending on this). I would rather do this step only once, when std::span will be more accessible

S-Dafarra commented 2 years ago

I tried to edit the SpanUnitTest as follows image

But I am able to compile :thinking:

S-Dafarra commented 2 years ago

See https://github.com/ami-iit/matio-cpp/commit/708827b321ce16be6e1db0919829f896e6e6e178