C/C++ Weird libc++ experience

jbodenmann

Well-Known Member

Reaction score: 227
Messages: 433

I'm sorry for the weird title of this thread but I'm really not sure what I'm currently experience.
The problem I am experiencing is that devel/llvm13 doesn't know about std::invocable.

Minimum test case as follows:

main.cpp:
Code:
#include <concepts>

void func(int);

int main()
{
    return std::invocable<decltype(&func), int>;
}

CMakeLists.txt:
Code:
cmake_minimum_required(VERSION 3.21)
project(llvm_test)

set(TARGET llvm_test)

add_executable(${TARGET})

target_compile_features(
    ${TARGET}
    PRIVATE
        cxx_std_20
)

target_sources(
    ${TARGET}
    PRIVATE
        main.cpp
)

Compilation output:
Code:
====================[ Build | llvm_test | Debug ]===============================
/usr/local/bin/cmake --build /home/jbo/projects/llvm_test/cmake-build-debug --target llvm_test -- -j 9
Scanning dependencies of target llvm_test
[ 50%] Building CXX object CMakeFiles/llvm_test.dir/main.cpp.o
/home/jbo/projects/llvm_test/main.cpp:6:42: error: expected '(' for function-style cast or type construction
    return std::invocable<decltype(&func), int>;
                          ~~~~~~~~~~~~~~~^
/home/jbo/projects/llvm_test/main.cpp:6:17: error: no member named 'invocable' in namespace 'std'
    return std::invocable<decltype(&func), int>;
           ~~~~~^
2 errors generated.
gmake[3]: *** [CMakeFiles/llvm_test.dir/build.make:72: CMakeFiles/llvm_test.dir/main.cpp.o] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:83: CMakeFiles/llvm_test.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:90: CMakeFiles/llvm_test.dir/rule] Error 2
gmake: *** [Makefile:124: llvm_test] Error 2

The test case above compiles fine with both devel/gcc10 and devel/gcc11. But also devel/llvm-devel is struggling on this one.
I'm aware that std::invocable is a concept provided by the STL. It's not a compiler built-in language feature. Clang by default uses libc++.

The confusing part is that the same code on godbolt works fine, even when explicitly stating the use of libc++: https://godbolt.org/z/1P9b549qa
This would indicate that libc++ shipping with clang 13 implements std::invocable.

Could somebody explain to me what I'm missing here?
 

Zirias

Son of Beastie

Reaction score: 1,698
Messages: 2,868

Does cmake really set the -std=c++20 flag? Unfortunately impossible to see in the build log. Standard libraries often hide declarations based on the standard version...
 
OP
jbodenmann

jbodenmann

Well-Known Member

Reaction score: 227
Messages: 433

Interesting... setting set(CMAKE_CXX_STANDARD 20) actually makes this compile as expected.

I have to check the cmake documentation. So far I have been using
Code:
target_compile_features(
    ${TARGET}
    PRIVATE
        cxx_std_20
)
successfully with both GCC and MSVC.
 

Zirias

Son of Beastie

Reaction score: 1,698
Messages: 2,868

Well, I have no idea about cmake (never used it), but the truth lies in the flags passed to the compiler :cool: maybe the construct you're using just checks for compiler support?

About GCC and MSVC: If you don't explicitly request a standard version, you get whatever the compiler defaults to.
 
OP
jbodenmann

jbodenmann

Well-Known Member

Reaction score: 227
Messages: 433

I agree with what you say. I merely meant to communicate that I have used this successfully before but will certainly need to look into it.

From the cmake documentation of target_compile_features():
Specifies compiler features required when compiling a given target.
[...]
If the use of the feature requires an additional compiler flag, such as -std=gnu++11, the flag will be added automatically.

From other projects I have seen this working (by also checking the compiler flags passed to the compiler as well as by being able to use C++17 and C++20 features successfully).

I'll certainly check which flags are passed to clang in my test case above.
 

Erichans

Member

Reaction score: 66
Messages: 77

Which version of CMake are you using?
Which version of llvm are you using? clang -v

Have you tried to get CMake to output more info on the generated llvm command line command options generated?
Activate CMAKE_VERBOSE_MAKEFILE (see: CMAKE_VERBOSE_MAKEFILE) e.g.:
set(CMAKE_VERBOSE_MAKEFILE ON)

Compare the various outputs (especially those that differ in the desired result); for example with set(CMAKE_CXX_STANDARD 20) versus not with that set command and only:
Code:
target_compile_features(
    ${TARGET}
    PRIVATE
        cxx_std_20
)
 

unitrunker

Aspiring Daemon

Reaction score: 252
Messages: 551

Would this not do what you want?

#include <functional>

std::function<void(int)> delegate = func;

delegate(123);
 
Top