2

I'm trying to compile the following code:

#include <boost/optional.hpp>
void foo(boost::optional<unsigned> x = boost::none);

placed in the file a.cu, with the CUDA compiler, using the following command line:

nvcc a.cu -c --std=c++11 -I/opt/boost/include

but I get a bunch of errors:

a.cu:2:53: error: conversion from ‘const boost::none_t(boost::none_t::init_tag (*)())’ to ‘boost::optional<unsigned int>’ is ambiguous
 void foo(boost::optional<unsigned> x = boost::none);
                                                     ^
/opt/boost/include/boost/optional/optional.hpp:805:1: note: candidate: boost::optional<T>::optional(boost::optional<T>::rval_reference_type) [with T = unsigned int; boost::optional<T>::rval_reference_type = unsigned int&&] <near match>
     optional ( rval_reference_type val ) : base( boost::forward<T>(val) )
 ^   ~~~~
/opt/boost/include/boost/optional/optional.hpp:805:1: note:   conversion of argument 1 would be ill-formed:
a.cu:2:53: error: invalid conversion from ‘const boost::none_t (*)(boost::none_t::init_tag (*)())’ to ‘unsigned int’ [-fpermissive]
 void foo(boost::optional<unsigned> x = boost::none);
                                                     ^
/opt/boost/include/boost/optional/optional.hpp:800:1: note: candidate: boost::optional<T>::optional(boost::optional<T>::argument_type) [with T = unsigned int; boost::optional<T>::argument_type = const unsigned int&] <near match>
     optional ( argument_type val ) : base(val) {}
 ^   ~~~~
/opt/boost/include/boost/optional/optional.hpp:800:1: note:   conversion of argument 1 would be ill-formed:
a.cu:2:53: error: invalid conversion from ‘const boost::none_t (*)(boost::none_t::init_tag (*)())’ to ‘unsigned int’ [-fpermissive]
 void foo(boost::optional<unsigned> x = boost::none);

Why does this happen, and can I circumvent the problem while still actually using boost::optional in (host-side) code compiled with nvcc?

Additional information:

  • The code compiles fine with g++ 6.3.0 (my distribution's compiler).
  • This code (or rather, similar code) used to compile and work on an earlier Linux distribution I was using, where the compiler was g++ 5.4.x .
  • I've tried this with Boost versions 1.65.1 and 1.69.0 .
  • I've tried this with CUDA versions 9.2.88 and 10.0.130 .
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    "what can I do about it?" 1. file a boost issue 2. file a NVIDIA bug 3. segregate the boost code into a .cpp file, put your CUDA code in a .cu file, and use wrapper functions to tie the functionality together – Robert Crovella Feb 09 '19 at 22:16
  • 1
    @RobertCrovella: See edit. But I will file issues. I'm guessing the problem is with nvcc rather than Boost. – einpoklum Feb 09 '19 at 22:46

2 Answers2

2

I had the exact same error and was able to get this to work with this modification:

    #define BOOST_OPTIONAL_USE_OLD_DEFINITION_OF_NONE
    #include <boost/optional.hpp>

This is using CUDA 10.0.130, g++ 7.3.0, and Boost 1.68.0.

1

A partial answer to the second question:

You could consider using Andrzej Krzemieński's neat and self-contained implementation of an optional instead of boost::optional. It works with C++11, which is what you seem to be doing.

einpoklum
  • 118,144
  • 57
  • 340
  • 684