centos7.9, gcc/g++ 9.3.1, g++ main.cpp -o test ok, but cmake build faild, could anybody help me?

  1. OS: centos7.9
  2. gcc: 9.3.1
  3. main.cpp:
    #include
    using namespace std;

template <typename KeyT, typename T>
class MyHash {
public:
MyHash() {}

uint64_t preHash(const KeyT& key) { return preHash(key, std::is_integral<KeyT>()); } //std::is_integral 检查T是否为整数
uint64_t preHash(const KeyT& key, std::true_type) { return key; }
uint64_t preHash(const KeyT& key, std::false_type) { return static_cast<uint64_t>(std::hash<KeyT>{}(key)); }

uint64_t typeTest(const KeyT& key) { return key; }

private:

};

int main()
{
MyHash<int, std::string> hash1;
std::cout << "hash int: " << hash1.preHash(12) << std::endl;

MyHash<std::string, std::string> hash2;
std::cout << "hash string: " << hash2.preHash("lidong") << std::endl;

MyHash<__uint128_t, std::string> hash4;
std::cout << "hash __uint128_t: " << hash4.preHash(1211111111) << std::endl;
return 0;	

}

  1. CMakeLists.txt

CMakeList.txt: testt project

cmake_minimum_required (VERSION 3.18)

project (hash-test-cmake)

#include cxx compilerFlag
include(CheckCXXCompilerFlag)

CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++1y" COMPILER_SUPPORTS_CXX14)
CHECK_CXX_COMPILER_FLAG("-std=c++1z" COMPILER_SUPPORTS_CXX17)

if(COMPILER_SUPPORTS_CXX17)
message("-- use c++17")
set(CMAKE_CXX_STANDARD 17)
elseif(COMPILER_SUPPORTS_CXX14)
message("-- use c++14")
set(CMAKE_CXX_STANDARD 14)
elseif(COMPILER_SUPPORTS_CXX11)
message("-- use c++11")
set(CMAKE_CXX_STANDARD 11)
else()
message("-- not support c++11 or above version")
endif(COMPILER_SUPPORTS_CXX17)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include_directories(.)
include_directories(external)

add_executable (hash-test main.cpp)

  1. g++ main.cpp -o test ok

  2. ./test
    [root@centos-dev hash-test-cmake]# ./test
    hash int: 12
    hash string: 6250863396115393637
    hash __uint128_t: 1211111111

  3. cmake build error:
    [root@centos-dev build]#cmake
    – The C compiler identification is GNU 9.3.1
    – The CXX compiler identification is GNU 9.3.1
    – Detecting C compiler ABI info
    – Detecting C compiler ABI info - done
    – Check for working C compiler: /usr/bin/cc - skipped
    – Detecting C compile features
    – Detecting C compile features - done
    – Detecting CXX compiler ABI info
    – Detecting CXX compiler ABI info - done
    – Check for working CXX compiler: /usr/bin/c++ - skipped
    – Detecting CXX compile features
    – Detecting CXX compile features - done
    – Performing Test COMPILER_SUPPORTS_CXX11
    – Performing Test COMPILER_SUPPORTS_CXX11 - Success
    – Performing Test COMPILER_SUPPORTS_CXX14
    – Performing Test COMPILER_SUPPORTS_CXX14 - Success
    – Performing Test COMPILER_SUPPORTS_CXX17
    – Performing Test COMPILER_SUPPORTS_CXX17 - Success
    – use c++17
    – Configuring done
    – Generating done
    – Build files have been written to: /usr/work/study/hash-test-cmake/build

[root@centos-dev build]# make
[ 50%] Building CXX object CMakeFiles/hash-test.dir/main.cpp.o
/usr/work/study/hash-test-cmake/main.cpp: In instantiation of ‘uint64_t MyHash<KeyT, T>::preHash(const KeyT&, std::false_type) [with KeyT = __int128 unsigned; T = std::basic_string; uint64_t = long unsigned int; std::false_type = std::integral_constant<bool, false>]’:
/usr/work/study/hash-test-cmake/main.cpp:9:82: required from ‘uint64_t MyHash<KeyT, T>::preHash(const KeyT&) [with KeyT = __int128 unsigned; T = std::basic_string; uint64_t = long unsigned int’
/usr/work/study/hash-test-cmake/main.cpp:28:63: required from here
/usr/work/study/hash-test-cmake/main.cpp:11:101: error: could not convert ‘()’ from ‘’ to ‘std::__hash_enum<__int128 unsigned, false>’
11 | uint64_t preHash(const KeyT& key, std::false_type) { return static_cast<uint64_t>(std::hash{}(key)); }
| ~~~~~~~~~~~^
| |
|
/usr/work/study/hash-test-cmake/main.cpp:11:101: error: use of deleted function ‘std::hash<__int128 unsigned>::~hash()’
In file included from /opt/rh/devtoolset-9/root/usr/include/c++/9/string_view:43,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/basic_string.h:48,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/string:55,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/locale_classes.h:40,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/bits/ios_base.h:41,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/ios:42,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/ostream:38,
from /opt/rh/devtoolset-9/root/usr/include/c++/9/iostream:39,
from /usr/work/study/hash-test-cmake/main.cpp:1:
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/functional_hash.h:101:12: note: ‘std::hash<__int128 unsigned>::hash()’ is implicitly deleted because the default definition would be ill-formed:
101 | struct hash : __hash_enum<_Tp>
| ^
~
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/functional_hash.h:101:12: error: ‘std::__hash_enum<_Tp, >::__hash_enum() [with _Tp = __int128 unsigned; bool = false]’ is private within this context
/opt/rh/devtoolset-9/root/usr/include/c++/9/bits/functional_hash.h:83:7: note: declared private here
83 | ~__hash_enum();
| ^
make[2]: *** [CMakeFiles/hash-test.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/hash-test.dir/all] Error 2
m

  1. There’s no build-in specialization of std::hash for __uint128_t, so I’d expect an error.
  2. The issue may boil down to the compiler flags. Like the most trivial fact that you’re enabling c++17 in your CMake file but do not do the same on the command line

you mean I need delete to use c++17 in my cmakefilelist.txt?

No - I say that you don’t use the same flags, so you could just try to find out which flags are set by CMake and find which is causing the trouble.

Additionally I believe the error is correct given that there’s no specialisation of std::hash for your type, so you’d have to provide specialisation for that by yourself. See for example: c++ - std::hash for __uint128_t - Stack Overflow

many thanks, that’s not too easy, I think I shoud change the __uint128_t to uint64_t.