C++17 refuses to compile example if constexpr giving expected ‘(’ before ‘constexpr’ - g++

I am trying out this text-book example of using if constexpr and I am getting error expected ‘(’ before ‘constexpr’ when compiling.
I am compiling with g++ -std=c++17 test.cpp so the version should support it. Visual Studio Code understands this and hints that this expression will be compiled to number 120 (correct).
#include <iostream>
using std::cout;
using std::endl;
template <int N>
constexpr int fun() {
if constexpr (N <= 1) {
return 1;
} else {
return N * fun<N - 1>();
}
}
int main(int argc, char** argv) {
cout << fun<5>() << endl;
return 0;
}
This code should compile error-free

You need a more recent version of GCC. Version 7 and up support this. See:
https://en.cppreference.com/w/cpp/compiler_support#cpp17
(Search for "constexpr if".)
So upgrade your GCC version. If you're on Ubuntu, you can add the Toolchain PPA to install the latest available GCC version:
https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test

Related

Linker error in boost serialization of custom archive

I've tried to implement an own archive type for boost serialization following official boost example to write archives.
#include <iostream>
#include <vector>
#include <boost/serialization/nvp.hpp>
#include "boost/serialization/vector.hpp"
#include <boost/archive/detail/common_oarchive.hpp>
#include <boost/archive/detail/register_archive.hpp>
#include <boost/archive/detail/archive_serializer_map.hpp>
class complete_oarchive : public boost::archive::detail::common_oarchive<complete_oarchive>
{
friend class boost::archive::save_access;
template<class T>
void save(T & t){
std::cout << "saved data\n";
}
public:
void save_binary(void *address, std::size_t count){
}
};
template class boost::archive::detail::archive_serializer_map<complete_oarchive>;
template class boost::archive::detail::common_oarchive<complete_oarchive>;
BOOST_SERIALIZATION_REGISTER_ARCHIVE(complete_oarchive)
int main(int argc, char *argv[])
{
std::vector<double> testVector = {1, 2, 3, 4};
complete_oarchive oa;
std::vector<double>* pVec = &testVector;
oa << BOOST_SERIALIZATION_NVP(testVector);
oa << BOOST_SERIALIZATION_NVP(pVec);
return 0;
}
Compiling this example with
g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux/demo.o.d" -o build/Debug/GNU-Linux/demo.o demo.cpp
g++ -o dist/Debug/GNU-Linux/serializationdemo build/Debug/GNU-Linux/demo.o -lboost_serialization
leads to the following linker error
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:222: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::insert(boost::archive::detail::basic_serializer const*)'
build/Debug/GNU-Linux/demo.o: In function `boost::archive::detail::pointer_oserializer<complete_oarchive, std::vector<double, std::allocator<double> > >::~pointer_oserializer()':
/opt/tools/boost/boostRdk-1.66.0/include/boost/archive/detail/oserializer.hpp:227: undefined reference to `boost::archive::detail::archive_serializer_map<complete_oarchive>::erase(boost::archive::detail::basic_serializer const*)'
collect2: error: ld returned 1 exit status
It seems that serializing a pointer in
oa << BOOST_SERIALIZATION_NVP(pVec);
leads to this error. After deletion of this line everything works fine and the result is as expected.
Does anybody have experience in writting own serialization archives?
A simimal Problem was solved here
https://groups.google.com/forum/#!topic/boost-list/CMoDosGZUo8
but I wasn't able to solve this by forward declarations.
I solved the issue by replacing
#include <boost/archive/detail/archive_serializer_map.hpp>
by
#include <boost/archive/impl/archive_serializer_map.ipp>

getting error in running cmake std Tutorial step 2 example

I am totally new to cmake and its syntax .But fortunately I am able to run the cmake tutorial step 1 as per the introductions mention on below links :
https://cmake.org/cmake/help/latest/guide/tutorial/index.html
But I am totally stucked at step 2 project to run using cmake.
I have created the step 2 project and understand the syntax to link the library for doing square root of a number, But I did not understand how to run this as I am getting below error :
user#server:~/TER_CMAKE/Tutorial/step2_build$ cmake ../step2
CMake Error at CMakeLists.txt:19 (add_subdirectory):
The binary directory
/home/user/TER_CMAKE/Tutorial/step2/MathFunctions
is already used to build a source directory. It cannot be used to build
source directory
/home/user/TER_CMAKE/Tutorial/step2/MathFunctions
Specify a unique binary directory name.
-- Configuring incomplete, errors occurred!
The example is available at below location for step 2 under heading Adding a Library (Step 2)..
https://moodle.rrze.uni-erlangen.de/pluginfile.php/14829/mod_resource/content/5/CMakeTutorial.pdf
My intention is to run my example this way
step2_build$ cmake ../step2
step2_build$ cmake --build .
step2_build$ ./Tutorial 121
As I am not sure that is it good to ask this way on this platform ,But as I do not have any other guidance .I am doing this by my own .
Note: I do not wants to use any tool to run my step 2 example.I wants to run everything using command prompt and cmake command only .where I can understand the cmake .
Edit:
Adding my CMakeLists.txt =
cmake_minimum_required(VERSION 3.5)
#set the project name
project(Tutorial VERSION 1.0)
#specify the c++ std
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
#Configure a header file to pass the version number to the source code
configure_file(TutorialConfig.h.in TutorialConfig.h)
#add the MathFunctions Library
add_subdirectory(MathFunctions)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
#add the executable
add_executable(Tutorial tutorial.cpp)
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_LIBS}
)
My Source tutorial.cpp file:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <string>
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
#include "TutorialConfig.h"
using namespace std;
int main(int argc, char* argv[])
{
if (argc < 2) {
cout << "Usage: " << argv[0] << " number" << endl;
return 1;
}
// convert input to double
const double inputValue = atof(argv[1]);
// calculate square root
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
cout << "The square root of " << inputValue << " is " << outputValue << endl;
return 0;
}
ToturialConfig.h.in file :
#define Tutorial_VERSION_MAJOR #Tutorial_VERSION_MAJOR#
#define Tutorial_VERSION_MINOR #Tutorial_VERSION_MINOR#
#cmakedefine USE_MYMATH
EDIT:
Step2 has a folder MathFuctions,Which has Cmake file mysqrt.cpp file
/TER_CMAKE/Tutorial/step2/MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
/TER_CMAKE/Tutorial/step2/MathFunctions/mysqrt.cpp
#include <iostream>
// a hack square root calculation using simple operations
double mysqrt(double x)
{
if (x <= 0) {
return 0;
}
double result = x;
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {
result = 0.1;
}
double delta = x - (result * result);
result = result + 0.5 * delta / result;
std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
}
return result;
}
In case USE_MYMATH variable is set add_subdirectory(MathFunctions) is invoked twice. You need to decide and remove one of the occurrences on lines 16 and 19 in you CMakeLists.txt.
Two issues I can see:
You're adding the subdirectory "MathFunctions" twice when you configure the build with -DUSE_MYMATH=ON. This is why you are getting "CMake Error at CMakeLists.txt:19 (add_subdirectory):"
To fix, remove
#add the MathFunctions Library
add_subdirectory(MathFunctions)
and rely on
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
In your CMakeLists.txt file, you are doing
target_include_directories(Tutorial PUBLIC
"${PROJECT_BINARY_DIR}"
${EXTRA_LIBS}
)
Instead of
${EXTRA_LIBS}
It should be
${EXTRA_INCLUDES}
in Discourse Cmake Org -- help with tutorial step 2
Josef Angstenberger
jtxa said
The files in Step3 are the expected result if you do everything from Step2.
Can you please compare your files against the ones from Step3 to see if there are any relevant differences?
Blockquote
Marshallb's solution will solve nahesh relkar's problem
Loading Step2/CMakeLists.txt and Step3/CMakeLists.txt into vimdiff helped me to fix mine

Why do I need separable compilation?

I have the code shown below. As far as I understood, separable compilation must be turned on when
CUDA device code is separated into .h and .cu files
Use ObjectA's device code into Object's B device code
however, in my main function I am not having any of the cases above. Could you tell me why do I have to set separable compilation for this sample project?
BitHelper.h
#pragma once
#include <cuda_runtime.h>
#define COMPILE_TARGET __host__ __device__
class BitHelper
{
public:
COMPILE_TARGET BitHelper();
COMPILE_TARGET ~BitHelper();
COMPILE_TARGET static void clear(unsigned int& val0);
};
BitHelper.cu
#include "bithelper.h"
BitHelper::BitHelper()
{}
BitHelper::~BitHelper()
{}
void BitHelper::clear(unsigned int& val0)
{
val0 = 0x0000;
}
Consume_BitHelper.h
#pragma once
class Consume_BitHelper
{
public:
void apply();
private:
bool test_cpu();
bool test_gpu();
};
Consume_BitHelper.cu
#include "consume_bithelper.h"
#include <cuda_runtime.h>
#include <iostream>
#include "bithelper.h"
__global__
void myKernel()
{
unsigned int FLAG_VALUE = 0x2222;
printf("GPU before: %d\n", FLAG_VALUE);
BitHelper::clear(FLAG_VALUE);
printf("GPU after: %d\n", FLAG_VALUE);
}
void Consume_BitHelper::apply()
{
test_cpu();
test_gpu();
cudaDeviceSynchronize();
}
bool Consume_BitHelper::test_cpu()
{
std::cout << "TEST CPU" << std::endl;
unsigned int FLAG_VALUE = 0x1111;
std::cout << "CPU before: " << FLAG_VALUE << std::endl;
BitHelper::clear(FLAG_VALUE);
std::cout << "CPU after : " << FLAG_VALUE << std::endl;
return true;
}
bool Consume_BitHelper::test_gpu()
{
std::cout << "TEST GPU" << std::endl;
myKernel << <1, 1 >> > ();
return true;
}
main.cu
#include "consume_bithelper.h"
#include "bithelper.h"
#include <iostream>
int main(int argc, char** argv)
{
Consume_BitHelper cbh;
cbh.apply();
std::cout << "\nPress any key to continue...";
std::cin.get();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(cuda_class LANGUAGES CXX CUDA)
#BitHelper needs separable compilation because we have separated declaration from definition
add_library(bithelper_lib STATIC bithelper.cu)
set_property(TARGET bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
#Consume_BitHelper needs separable compilation because we call BitHelper's device code
#from Consume_BitHelper's kernel
add_library(consume_bithelper_lib STATIC consume_bithelper.cu)
set_property(TARGET consume_bithelper_lib PROPERTY CUDA_SEPARABLE_COMPILATION ON)
target_link_libraries(consume_bithelper_lib bithelper_lib)
#We only call CPU code so no need of separable compilation?
add_executable(${PROJECT_NAME} main.cu)
target_link_libraries(${PROJECT_NAME} bithelper_lib consume_bithelper_lib)
The errors I'm getting are these
EDIT
According to Robert Crovella's post Consume_BitHelper.cu uses BitHelper::clear defined in a separate compilation unit.
Does it mean I have to activate only separate compilation for BitHelper?
Since separate compilation has to do only with device code called from device code.
Why am I getting the mentioned errors when separate compilation is NOT on for cuda_class? (which is the executable created from CMake and is not calling any device code)
Separable compilation has to do with how the compiler handles function calls. In exchange for a little bit of overhead, you get the ability to make true function calls and thus access code from other "compilation units" (i.e. .cu source files).
As GPU programmers are obsessed with performance (particularly the extra registers that get used when separable compilation is enabled) Nvidia made it an option instead of default.
You should only need separable compilation for .cu files that access functions/globals defined in other .cu files.

Why doesn't CMake find Boost?

i try to use Boost unit test framework to test my static library but CMake cannot find Boost in spite of BOOST_ROOT, CMAKE_INCLUDE_PATH, CMAKE_LIBRARY_PATH are set before call to find_package. Actually i've tried a lot of options based on the answers to similar question but still without any success.
cmake version:3.6.1
boost version:1.60.0
Here is link to my project on GitHub
And here is log output from TravisCI
CMakeLists.txt:
cmake_minimum_required(VERSION ${cmake_version})
project(${LibName}_test)
set(Boost_DEBUG ON)
set(Boost_DETAILED_FAILURE_MSG ON)
set(BOOST_ROOT $ENV{BOOST_ROOT})
message(STATUS "BOOST_ROOT >> ${BOOST_ROOT}")
set(BOOST_LIBRARYDIR $ENV{BOOST_ROOT}/lib)
set(BOOST_INCLUDEDIR $ENV{BOOST_ROOT}/include)
enable_testing()
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "$ENV{BOOST_ROOT}/include")
SET(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "$ENV{BOOST_ROOT}/lib")
find_package(Boost 1.60.0 EXACT REQUIRED COMPONENTS unit_test_framework)
#if(Boost_FOUND)
include_directories("${LIB_HEADERS}")
add_executable(test_executable
main.cpp
SomeClass_test.cpp
)
target_include_directories(test_executable PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries(test_executable
#${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
Boost::unit_test_framework
${LibName}
)
add_test(NAME test1 COMMAND test_executable)
#else()
# message(STATUS "No Boost library were found!")
#endif()
main.cpp:
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <iostream>
// initialization function:
bool init_unit_test()
{
return true;
}
// entry point:
int main(int argc, char * argv[]) {
// insert code here...
std::cout << "Boost version: "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minor version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
return boost::unit_test::unit_test_main( &init_unit_test, argc, argv );
}
SomeClass_test.cpp:
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include "config.h"
#include "Rectangle.h"
#include "SomeClass_test.hpp"
BOOST_AUTO_TEST_CASE(int_test)
{
int i = 2;
BOOST_TEST(i);
BOOST_TEST(i == 2);
}
BOOST_AUTO_TEST_CASE(area_test)
{
Rectangle rect;
rect.set_values(2, 3);
BOOST_TEST(6 == rect.area());
}
BOOST_AUTO_TEST_CASE(config_test)
{
auto major = SimpleNet::Version::Major;
BOOST_TEST(0 == major);
}

Mingw32 std::isnan with -ffast-math

I am compiling the following code with the -ffast-math option:
#include <limits>
#include <cmath>
#include <iostream>
int main() {
std::cout << std::isnan(std::numeric_limits<double>::quiet_NaN() ) << std::endl;
}
I am getting 0 as output. How can my code tell whether a floating point number is NaN when it is compiled with -ffast-math?
Note: On linux, std::isnan works even with -ffast-math.
Since -ffast-math instructs GCC not to handle NaNs, it is expected that isnan() has an undefined behaviour. Returning 0 is therefore valid.
You can use the following fast replacement for isnan():
#if defined __FAST_MATH__
# undef isnan
#endif
#if !defined isnan
# define isnan isnan
# include <stdint.h>
static inline int isnan(float f)
{
union { float f; uint32_t x; } u = { f };
return (u.x << 1) > 0xff000000u;
}
#endif
On linux, the gcc flag -ffast-math breaks isnan(), isinf() and isfinite() - there may be other related functions that are also broken that I have not tested.
The trick of wrapping the function/macro in parentheses also did not work (ie. (isnan)(x))
Removing -ffast-math works ;-)