Skip to content

Assignment to const value breaks clang++20 compilation #116

@lyinch

Description

@lyinch

When I try to compile nvblox v0.0.9 with clang++20 (and CXX_STANDARD 20).

$ clang++ -v
Ubuntu clang version 20.1.8 (++20250708082409+6fb913d3e2ec-1~exp1~20250708202428.132)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-20/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/11
Candidate multilib: .;@m64
Selected multilib: .;@m64
Found CUDA installation: /usr/local/cuda-12.9, version 

then it's failing because of an assignment to a const value:

In file included from /usr/local/include/nvblox/mapper/multi_mapper.h:18:
In file included from /usr/local/include/nvblox/experimental/ground_plane/ground_plane_estimator.h:23:
In file included from /usr/local/include/nvblox/experimental/ground_plane/ransac_plane_fitter.h:26:
In file included from /usr/local/include/nvblox/sensors/pointcloud.h:24:
In file included from /usr/local/include/nvblox/sensors/camera.h:19:
In file included from /usr/local/include/nvblox/interpolation/interpolation_2d.h:19:
In file included from /usr/local/include/nvblox/sensors/image.h:518:
/usr/local/include/nvblox/sensors/internal/impl/image_impl.h:265:27: error: cannot assign to return value because function 'operator()' returns a const value
  265 |   mask_(row_idx, col_idx) = image::kMaskedValue;
      |   ~~~~~~~~~~~~~~~~~~~~~~~ ^
/usr/local/include/nvblox/sensors/image.h:132:30: note: function 'operator()' which returns const-qualified type 'ElementType &' (aka 'const unsigned char &') declared here
  132 |   __host__ __device__ inline ElementType& operator()(const int row_idx,
      |                              ^~~~~~~~~~~~
1 error generated.

The issue seems to be that in image.h:

 private:
  ImageView<const uint8_t> mask_;

but then at some point, it's being assigned to:

template <typename ElementType>
void MaskedImageView<ElementType>::setMasked(const int row_idx,
                                             const int col_idx) {
  mask_(row_idx, col_idx) = image::kMaskedValue;
}

but something is a little odd here, because there are two () overloads, one const and one w/o:

  __host__ __device__ inline const ElementType& operator()(
      const int row_idx, const int col_idx) const {
    return image::access(row_idx, col_idx, stride_num_elements_, data_);
  }
  __host__ __device__ inline ElementType& operator()(const int row_idx,
                                                     const int col_idx) {
    return image::access(row_idx, col_idx, stride_num_elements_, data_);
  }

(and also two access() functions), but by using <const uint8_t> as ElementType, it seems like it breaks the idea of having const + non-const accessors.

A friendly LLM provided this workaround:

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  # The nvblox headers shipped in this environment currently trip clang's
  # eager template parsing (see MaskedImageView::setMasked in
  # nvblox/sensors/internal/impl/image_impl.h). We don't use that API, so delay
  # template parsing to keep the build clean without patching system headers.
  target_compile_options(foo PRIVATE
    -fdelayed-template-parsing
    -Wno-delayed-template-parsing-in-cxx20
  )
endif()

I can successfully compile and use nvblox that way. Not sure how it behaves when I accidentally instantiate these templates.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions