I'm trying to set up c++11 to my project on visual studio, and to find out which version the compiler used by default I used the following code:
#include <iostream>
int main(){
#if __cplusplus==201402L
std::cout << "C++14" << std::endl;
#elif __cplusplus==201103L
std::cout << "C++11" << std::endl;
#elif __cplusplus==199711L
std::cout << "C++" << std::endl;
#elif __cplusplus==201703L
std::cout << "C++17" << std::endl;
#elif __cplusplus==1
std::cout << "C+" << std::endl;
#endif
int* i = nullptr;
return 0;
}
Having output c++ (98) I tried to force the compiler to use c++11 via the CMakeLists like this:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
The output was always C ++ (98), so I added
int* i = nullptr;
and amazingly the output remains c++ (98) but the application works without problems. How is this "anomaly" explained and how do I know / decide which standard to use?
According to this question: Visual Studio 2012 __cplusplus and C++ 11 , provided by #paddy, this is a known bug with MSVC in that the version macro is set to C++98. You should compile with the /Zc:__cplusplus switch to change the version macro to the correct value.
Related
I started my study with OneAPI SYCL but I normally use QtCreator as my IDE. I did a HelloSYCL project with CMake and works fine in the terminal and in the VSCode with OneAPI Extension as well, but didn't work in the QtCreator.
Every time I want to use SYCL I need to start ONEAPI environment with ". /opt/intel/oneapi/setvars.sh", but I don't know how to do it with QtCreator
Here is the way I'm compile
mkdir build; cd build
cmake -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -G Ninja -S .. -DCMAKE_PREFIX_PATH="/opt/intel/oneapi/compiler/latest/linux/cmake/SYCL/" -DSYCL_INCLUDE_DIR=/opt/intel/oneapi/compiler/latest/linux/include/sycl -DSYCL_LIBRARY_DIR=/opt/intel/oneapi/compiler/latest/linux/lib
cmake_minimum_required(VERSION 3.22)
project(testSYCL LANGUAGES CXX)
if(UNIX)
set(CMAKE_C_COMPILER icx)
set(CMAKE_CXX_COMPILER dpcpp)
endif(UNIX)
list(APPEND CMAKE_MODULE_PATH "/opt/intel/oneapi/compiler/2021.4.0/linux/")
list(APPEND CMAKE_MODULE_PATH "/opt/intel/oneapi/compiler/2021.4.0/linux/cmake/SYCL/")
find_package(IntelDPCPP REQUIRED)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release" CACHE PATH "Build Type" FORCE)
endif()
add_executable(testSYCL main.cpp)
#include <iostream>
#include <iomanip>
#include <CL/sycl.hpp>
int main()
{
for ( const auto& plataform : sycl::platform::get_platforms() ) {
std::cout << "=========================================================\n";
std::cout << std::setw(25);
std::cout << plataform.get_info<sycl::info::platform::name>() << "\n";
std::cout << plataform.get_info<sycl::info::platform::vendor>() << "\n";
std::cout << "Plataform: " << plataform.get_info<sycl::info::platform::version>() << "\n";
for ( const auto& device : plataform.get_devices() ) {
std::cout << "Devices\n";
std::cout << "Name: " << device.get_info<sycl::info::device::name>() << "\n";
std::cout << "Max Compute Units: " << device.get_info<sycl::info::device::max_compute_units>() << "\n";
std::cout << "Max Work Group Size: " << device.get_info<sycl::info::device::max_work_group_size>() << "\n";
std::cout << "Max Clock Frequency: " << device.get_info<sycl::info::device::max_clock_frequency>() << " MHz \n";
}
}
}
QtCreator CMake Error
QtCreator Custom Compiler added
The answer depends on the contents of setvars.sh. I assume this is a simple script setting environment variables.
One way to mimic it in QtCreator is to define a custom kit.
Go to Tools/Options/Kits. Highlight any kit you use and press "clone". Then, add to it manually the necessary environment variables in the field "Environment". Use this kit for your SYCL projects. This will work if your problem is caused by a compiler error.
If the problem occurs while running a program inside QtCreator, look at build/running options:
There you'll easily find options for changing the runtime or compile-time environment
I have inherited a piece of C++ code which has many #ifdef branches to adjust the behaviour depending on the platform (#ifdef __WIN32, #ifdef __APPLE__, etc.). The code is unreadable in its current form because these preprocessor directives are nested, occur in the middle of functions and even in the middle of multi-line statements.
I'm looking for a way of somehow specifying some preprocessor tags and getting out a copy of the code as if the code had been pre-processed with those flags. I'd like the #include directives to be left untouched, though.
Example:
#include <iostream>
#ifdef __APPLE__
std::cout << "This is Apple!" << std::endl;
#elif __WIN32
std::cout << "This is Windows" << std::endl;
#endif
would turn into:
#include <iostream>
std::cout << "This is Apple!" << std::endl;
after being processed by: tool_i_want example.cpp __APPLE__.
I've hacked a quick script that does something similar, but I'd like to know of better tested and more thorough tools. I am running a Linux distribution.
I have decided against just running the C-preprocessor because if I'm not mistaken it will expand the header files, which would make everything more unreadable.
Use unifdef. It is designed for that purpose.
Complementing Basile Starynkevitch's answer, I want to mention coan. The major advantage is that, when used with -m it does not require the user to unset all symbols they want undefined.
This code:
#include <iostream>
#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif
#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif
#ifdef __APPLE__
std::cout << "In an Apple platform" << std::endl;
#elif __linux__
std::cout << "In a Linux platform" << std::endl;
#endif
would result in this code if simply run as: unifdef -D__APPLE__ example.cpp:
#include <iostream>
#ifdef __ANDROID__
std::cout << "In Android" << std::endl;
#endif
#ifndef __WIN32
std::cout << "Not a Windows platform" << std::endl;
#endif
std::cout << "In an Apple platform" << std::endl;
Using unifdef one would need to use
unifdef -D__APPLE__ -U__ANDROID__ -U__WIN32 -U__linux__ example.cpp:
#include <iostream>
std::cout << "Not a Windows platform" << std::endl;
std::cout << "In an Apple platform" << std::endl;
This can get exhausting quickly when dealing with code considering several different platforms. With coan it's a matter of:
coan source -D__APPLE__ -m example.cpp.
I want to use a value declared in my CMakeLists.txt in my C++ code. I've tried to do like that :
ADD_DEFINITIONS( -D_MYVAR=1 )
and
#if -D_MYVAR == 1
#define var "someone"
#else
#define var "nobody"
#endif
int main(){
std::cout << "hello" << var << std::endl;
return 0;
}
But it doesn't work, and I don't understand why. Maybe I don't use ADD_DEFINITIONS correctly...
Ideally, I wish do something like that :
ADD_DEFINITIONS( -D_MYVAR=\"someone\" )
and
#define var D_MYVAR
int main(){
std::cout << "hello" << var << std::endl;
return 0;
}
Is it possible ?
Thanks !
add_definitions ( -DVARNAME=... )
is the correct way of using add_definitions.
To check for a constant then, use
#ifdef VARNAME
...
#endif
Thanks to πάντα ῥεῖ
His solution works for my first question, and I've could do that :
CMakeLists.txt:
ADD_DEFINITIONS( -D_VAR=\"myValue\" )
main.cpp:
#include <iostream>
#ifdef _VAR
#define TXT _VAR
#else
#define TXT "nobody"
#endif
int main(){
std::cout << "hello " << TXT << " !" << std::endl;
return 0;
}
Actually there is a much more elegant way to do this, that does not require to go through the C/C++ preprocessor. (I hate #ifdef...)
In CMakeLists.txt:
set( myvar "somebody" )
# Replaces occurrences of #cmake_variable# with the variable's contents.
# Input is ${CMAKE_SOURCE_DIR}/main.cpp.in,
# output is ${CMAKE_BINARY_DIR}/main.cpp
configure_file( main.cpp.in main.cpp #ONLY )
In main.cpp.in:
#include <iostream>
int main(){
// myvar below gets replaced
std::cout << "hello #myvar#" << std::endl;
return 0;
}
Note, however, that a file so configured gets saved in ${CMAKE_BINARY_DIR}, so you have to prefix it as such when listing it in the source files (as those default to ${CMAKE_SOURCE_DIR}):
add_library( myproject foo.cpp bar.cpp ${CMAKE_BINARY_DIR}/main.cpp )
As of CMake 3.12 add_definitions has been superseeded by other alternatives.
For this question, you should use add_compile_definitions in the same way you were using add_definitions:
add_compile_definitions( MY_VAR )
(note that the -D is not needed anymore).
And then in your *.cpp file:
#ifdef MY_VAR
// do something if var defined
#endif
This is my sample code:
#pragma execution_character_set("utf-8")
#include <boost/locale.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <iostream>
int main()
{
std::locale loc = boost::locale::generator().generate("");
std::locale::global(loc);
#ifdef MSVC
std::cout << boost::locale::conv::from_utf("grüßen vs ", "ISO8859-15");
std::cout << boost::locale::conv::from_utf(boost::locale::to_upper("grüßen"), "ISO8859-15") << std::endl;
std::cout << boost::locale::conv::from_utf(boost::locale::fold_case("grüßen"), "ISO8859-15") << std::endl;
std::cout << boost::locale::conv::from_utf(boost::locale::normalize("grüßen", boost::locale::norm_nfd), "ISO8859-15") << std::endl;
#else
std::cout << "grüßen vs ";
std::cout << boost::locale::to_upper("grüßen") << std::endl;
std::cout << boost::locale::fold_case("grüßen") << std::endl;
std::cout << boost::locale::normalize("grüßen", boost::locale::norm_nfd) << std::endl;
#endif
return 0;
}
Output on Windows 7 is:
grüßen vs GRÜßEN
grüßen
grußen
Output on Linux (openSuSE 12.3) is:
grüßen vs GRÜSSEN
grüssen
grüßen
On Linux the german letter 'ß' is converted to 'SS' as predicted, while this character remains unchanged on Windows.
Question: why is this so? How can I correct the conversion?
Some notes: Windows console codepage is set to 1252. In both cases locales are set to de_DE. I tried to replace the default locale setting in the listing above by "de_DE.UTF-8" - without any effect.
On Windows this code is compiled with Visual Studio 2013, on Linux with GCC 4.7, c++11 enabled.
Any suggestions are appreciated - thanks in advance for your support!
Windows doesn't do this conversion because "it would be too confusing" for developers if the string length changed all of a sudden. And boost presumably just delegates all the Unicode conversions to the underlying Windows APIs
Source
I guess the robust way to handle it would be to use a third-party Unicode library such as ICU.
I have written a dll that uses an abstract interface to allow access to the c++ class inside. When I load the library dynamically at run-time using the LoadLibrary() function using a simple console created in eclipse using g++ and call a function from within the dll I get the correct values returned. However when writing the same console program using qt-creator qt5 with the g++ compiler I get completely different results that are not correct.
All of this was written under Windows 7 64-bit but using the x86 side of it for the programs.
The code that calls the dll from eclipse looks as follows:
HMODULE hMod = ::LoadLibrary("libTestDll.dll");
if (hMod) {
cout << "Library Loaded" << endl;
CreateITestType create = (CreateITestType) GetProcAddress(hMod,
"GetNewITest");
ITest* test = create();
std::cout << test->Sub(20, 5) << std::endl;
std::cout << test->Sub(20, 3) << std::endl;
std::cout << test->Add(20, 5) << std::endl;
std::cout << test->Add(13, 4) << std::endl;
DeleteITestType del = (DeleteITestType) GetProcAddress(hMod,
"DeleteITest");
del(test);
test = NULL;
FreeLibrary(hMod);
}
This returns:
Library Loaded
15
17
25
17
The code that calls the dll from qt looks as follows:
HMODULE hMod = LoadLibrary(TEXT("libTestDll.dll"));
if(hMod)
{
CreateITestType create = (CreateITestType)GetProcAddress(hMod, "GetNewITest");
DeleteITestType destroy = (DeleteITestType)GetProcAddress(hMod, "DeleteITest");
ITest* test = create();
std::cout << test->Sub(20, 5) << std::endl;
std::cout << test->Sub(20, 3) << std::endl;
std::cout << test->Add(20, 5) << std::endl;
std::cout << test->Add(13, 4) << std::endl;
destroy(test);
test = NULL;
FreeLibrary(hMod);
}
And This returns:
1
-17
25
24
Both programs have the imports:
#include <windows.h>
#include <iostream>
#include "TestDll.h"
And finally the functions are implemented as follows:
int Test::Add(int a, int b)
{
return (a+b);
}
int Test::Sub(int a, int b)
{
return (a-b);
}
My question is where is the difference coming from seeing as the two programs are identical in both code and compiler, and how can this be fixed?
Did you also rebuild the DLL with qt-creator qt5 with the g++ compiler? If not, then what you've discovered is that if you don't use the exact same compiler, compiler options and settings, defines, and pretty much every other aspect of the build system, C++ interfaces are not typically ABI compatible.