0

This code gets rejected:

const std::optional<int> opt{5};
std::optional<volatile int> opt2 = opt;

But this is accepted:

const std::optional<int> opt{5};
std::optional<const int> opt2 = opt;

What is going on here?

In file included from /tmp/a.cpp:1:
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/optional:627:4: error: no matching function for call to 'operator new'
          ::new
          ^~
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/optional:1140:10: note: in instantiation of function template specialization 'std::_Optional_base_impl >::_M_construct' requested here
          this->_M_construct(std::forward(__args)...);
                ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/optional:1002:4: note: in instantiation of function template specialization 'std::optional::emplace' requested here
          emplace(*__t);
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/new:134:7: note: candidate function not viable: no known conversion from 'volatile int *' to 'const std::nothrow_t' for 2nd argument
void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/new:143:7: note: candidate function not viable: no known conversion from 'volatile int *' to 'std::align_val_t' for 2nd argument
void* operator new(std::size_t, std::align_val_t)
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/new:168:14: note: candidate function not viable: no known conversion from 'volatile int *' to 'void *' for 2nd argument
inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/new:120:7: note: candidate function not viable: requires 1 argument, but 2 were provided
void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/new:145:7: note: candidate function not viable: requires 3 arguments, but 2 were provided
void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&)
      ^
1 error generated.
Artefacto
  • 96,375
  • 17
  • 202
  • 225
  • 5
    I'm curious what problem you are facing that can be solved with an `std::optional`. – François Andrieux Nov 10 '20 at 02:35
  • [Works here](https://gcc.godbolt.org/z/qff67j) – chris Nov 10 '20 at 02:36
  • I'm not sure, but I would bet that `std::optional` is not compatible with a type `T` that is `volatile` qualified. – François Andrieux Nov 10 '20 at 02:36
  • 2
    Why would you want to use `std::optional`? I don't think `volatile` makes sense here or rather you should almost never use volatile. – ALX23z Nov 10 '20 at 02:37
  • This is clang10, btw. `static_assert(std::is_constructible_v, std::optional>);` passes – Artefacto Nov 10 '20 at 02:38
  • [Also compiles with Clang 10 here](https://gcc.godbolt.org/z/oh8T34). It's probably the standard library implementation then. – chris Nov 10 '20 at 02:39
  • the reason I care about volatile is only I'm wrapping arbitrary (to a point) functions, and these may have volatile qualifiers in the arguments (they're quite used in ruby, for instance). The reason I need to convert an optional into a optional are complicated but basically boil to my removing qualifiers in the argument conversion process to avoid having an explosion of template specializations – Artefacto Nov 10 '20 at 02:41
  • 3
    You misunderstand the purpose of volatile qualifier. And perhaps the functions you use also do so wrongly or you just don't use them correctly. Idk about Ruby but in Java volatile serves as atomics but in C++ volatile is unsuitable for this purpose. – ALX23z Nov 10 '20 at 03:10
  • @ALX23z I know about the volatile situation in C++ and that only Microsoft's compiler by default adds memory fences. In ruby it's used to prevent some variables from being optimized out and becoming invisible to the garbage collector. – Artefacto Nov 10 '20 at 03:17
  • By "in ruby" in mean in the C code of the runtime or native extensions, not in the ruby language itself. – Artefacto Nov 10 '20 at 03:23
  • I can understand there could be some need for a `volatite std::optional`, but a `std::optional ` makes no sense. As for the second set of statements, that's perfectly normal and expected. You can copy const values as much as you want, where you want. – Michaël Roy Nov 10 '20 at 05:25
  • @Artefacto I don't think you understand what the `volatile`means. It deinitely has nothing to do wiith garbge collection, There is no garbage collection in C++, so there are no language keyword related to garbage collection. MSVC does not add any fences to the code because of `volatile`, either. (...) – Michaël Roy Nov 10 '20 at 05:35
  • (...) `volatile` only prevents the compiler to optimize away or displace reads or writes to a variable. `volatile` is useless by itself in multi-core environments. In multi-core environments, it's used to avoid compiler optimization in very rare cases... It is used in `std::atomic<>`, because the pupose of `std::atomic<>` is to mimic `volatile` in muti-core environments. For single-core processors, it's only uuseful when dealing with variables that can be modified by interrupt routines. That's actually what the keyword was created for. – Michaël Roy Nov 10 '20 at 05:41
  • @MichaëlRoy garbage collection in ruby. it needs to know which values are still referred to, and it search registers and stack for the it. The volatile prevents situations where you have `VALUE v = ...; X *x = ; operation_that_may_call_gc(); /* x is now dangling because v was collected */`. Now I think you're right that `std::optional` hardly has a use case, but I'm writing a generic wrapping mechanism, and preferably I'd cover all cases. – Artefacto Nov 10 '20 at 10:09
  • @Artefacto We are talking about C++ here. C++ as a language has no concept of what Ruby is, and no concept of what garbage collection is. And I'm pretty sure Ruby has no concept of what is an interrupt. So volatile in c++ and volatile in Ruby have two very, very, different meanings. – Michaël Roy Nov 10 '20 at 10:28
  • @MichaëlRoy there is no volatile in Ruby. I'm talking here about the C (or C++) implementation of ruby (and its extensions). That's where `volatile` enters the picture – Artefacto Nov 10 '20 at 10:30
  • I understand... The implementation of Ruby is fairly old, shared_ptr didn't exist back then. If you can, try to avoid theiir aloocators and their garbage collection use shared_ptr as much as possible. Good luck! – Michaël Roy Nov 10 '20 at 10:36

0 Answers0