Search code examples
c++language-lawyerllvmclang++libc++

std::optional<std::unique_ptr<int>> is not constexpr?


Why is the following method not constexpr?

constexpr std::optional<std::unique_ptr<int>> test2(void) {
  return std::nullopt;
}

Clang gives me the following error:

[build] /.../<>.cxx:223:47: error: constexpr function's return type 'std::optional<std::unique_ptr<int>>' is not a literal type
[build]   223 | constexpr std::optional<std::unique_ptr<int>> test2(void) {
[build]       |                                               ^
[build] /nix/store/fsb7lmhyy01flrnviwjfz3fgm53w990v-libcxx-18.1.7-dev/include/c++/v1/optional:582:7: note: 'optional<std::unique_ptr<int>>' is not literal because it has base class '__optional_move_assign_base<unique_ptr<int, default_delete<int>>>' of non-literal type
[build]   582 |     : private __optional_move_assign_base<_Tp>,

I am using Clang-version: 18 and std=c++20

Can anyone give me some pointers?

I configured my environment using nix, so the error should be reproducible:

{ pkgs ? import <nixpkgs> {} }: pkgs.mkShell {
    nativeBuildInputs = with pkgs.buildPackages; [
        # system tools
        zsh
        git
        openssl

        # basic configuration
        pkgs.llvmPackages_18.stdenv
        pkgs.llvmPackages_18.libcxx
        pkgs.llvmPackages_18.libcxxStdenv
        pkgs.llvmPackages_18.bintools
        pkgs.llvmPackages_18.clang-tools
        cmake

        # ...
    ];
}

The same error occurs when using a class or a struct instead of an int.


Solution

  • constexpr std::unique_ptr is a C++23 library feature (P2273), so you need to use -std=c++23 for the compiler to work.

    Demo