team-charls/charls

cannot convert argument 1 from 'std::vector<uint8_t,std::allocator<uint8_t>>' to 'const void *'

malaterre opened this issue · 5 comments

I have not spent too much time on this, but recently I saw the following error popping in visual studio 2019:

Error C2664 'size_t charls::jpegls_encoder::encode(const void *,const size_t,const uint32_t) const': cannot convert argument 1 from 'std::vector<uint8_t,std::allocator<uint8_t>>' to 'const void *'

Code is simply:

  std::vector<uint8_t> destination;
  auto ret = charls::jpegls_decoder::decode(source, destination);
  auto frame_info = ret.first;
  auto interleave_mode = ret.second;
  std::vector<uint8_t> destination2 =
      charls::jpegls_encoder::encode(
          destination, frame_info, interleave_mode);

thanks, will check it out

@malaterre,

I was not able to reproduce the problem on CharLS v2.4.2 or the main branch with Visual Studio 2019 v16.11.29.

There was such an issue in the past: #155, but that has been resolved in v2.3.1

I was able to reproduce the problem. The actual error is:

Failed to specialize function template 'Container charls::jpegls_encoder::encode(const Container &,const charls::frame_info &,const charls::interleave_mode,const charls::encoding_options)'
note: With the following template arguments:
note: 'Container=std::vector<uint8_t,std::allocator<uint8_t>>'
note: 'T=uint8_t'

the MSVC compiler then tries to match on of the 2 member methods that are also called encode, but these fail also.
And even if they would match, a static function is called, not a member function.

The root cause is that MSVC fails to specialize the function template. It seems that this template function only works when MSVC is used in C++ standard conforming mode and not in legacy mode. By default VS creates .vcxproj files that use the /permissive- option. For CMake this option needs to be added explicitly:

Adding:
if(MSVC)
add_compile_options("/permissive-")
endif()

before add_executable(foo foo.cxx) in the file CMakeLists.txt ensures that MSVC is used in C++ standard conforming mode. Note: Using C++20 will also automatically enable this option.

Using /permissive- is highly recommended as it catches many errors that otherwise would only show when compiling the same source with gcc or clang. I have seen many problems in legacy code with templates when this option is enabled, because /permissive- is much more strict. This is actual the first time I see a template function that fails when /permissive- is not used.

Ok, thanks for tracking this down. I've updated cmake issue: