gtest: undefined reference to `operator+' - googletest

This is just an observation, but I don't understand where is the problem. I implement vector addition operator and everything is work pretty well in the main function. But when I tried to test it by Google Test I got the compilation error
In function `ZN15Basic_Dirs_Test8TestBodyEv':
C:/Users/home/Documents/clion/example/test/main.cpp:10: undefined reference
to `operator+(std::vector<int, std::allocator<int> > const&,
std::vector<int, std::allocator<int> > const&)'
It compiles, however, when I remove src/class.cpp file. Could you tell me how it works? :)
The code is below.
src/class.h
#ifndef EXAMPLE_CLASS_H
#define EXAMPLE_CLASS_H
#include <vector>
std::vector<int> operator+(const std::vector<int>& a, const std::vector<int>& b);
#endif //EXAMPLE_CLASS_H
src/class.cpp
#include "class.h"
std::vector<int> operator+(const std::vector<int>& a, const std::vector<int>& b) {
if (a.size() != b.size()) {
std::cerr << "vectors are not of the same size!\n";
exit(1);
}
std::vector<int> res(a.size());
for (unsigned i = 0; i < a.size(); ++i) {
res[i] = a[i] + b[i];
}
return res;
}
test/main.cpp
#include "class.h"
#include <gtest/gtest.h>
using namespace std;
TEST(Basic, Dirs) {
std::vector<int> a = {1, 1, 0};
std::vector<int> b = {2, 1, 0};
std::vector<int> c = a+b;
EXPECT_EQ(c[0], 3);
EXPECT_EQ(c[1], 2);
EXPECT_EQ(c[2], 0);
}
./CMakeLists
cmake_minimum_required(VERSION 3.7)
project(example)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES src/main.cpp src/class.cpp)
add_subdirectory(test)
add_executable(example ${SOURCE_FILES})
test/CMakeLists
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_subdirectory("../lib/googletest" "${CMAKE_CURRENT_BINARY_DIR}/gtest_build")
include_directories(../lib/googletest/googletest/include)
include_directories(../src/)
add_executable(runtest main.cpp)
target_link_libraries(runtest gtest gtest_main)

You forgot to link your runtest gtest executable against your example:
./CMakeLists
cmake_minimum_required(VERSION 3.7)
project(example)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES src/main.cpp src/class.cpp)
add_executable(example ${SOURCE_FILES})
add_subdirectory(test)
test/CMakeLists
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_subdirectory("../lib/googletest" "${CMAKE_CURRENT_BINARY_DIR}/gtest_build")
include_directories(../lib/googletest/googletest/include)
include_directories(../src/)
add_executable(runtest main.cpp)
target_link_libraries(runtest gtest gtest_main example)
Also not that it might be better to actually define your example as a shared library instead of executable (just remove the main function - you probably don't need it anyway):
add_library(example SHARED ${SOURCE_FILES})

Related

How to improve the C++ code to get similar efficiency as in the Fortran code with arrays

There are two codes in Fortran and C++ with simple array manipulations with different declarations of arrays for C++. Let me know how to improve C++ code to get similar efficiency as in the Fortran code. The duration of runs in seconds is summarized below.
The Fortran program:
! fort.f90
PARAMETER ( N=1000000, M=10000 )
REAL*8, ALLOCATABLE :: D(:)
ALLOCATE(D(N))
A=1.0
DO J=1,M
DO I=1,N
D(I)=A+I+J
ENDDO
ENDDO
END
The Cpp program:
// main.cpp
using namespace std;
using namespace blitz;
int main(int argc, char* argv[]){
int N=1000000, M=10000;
double* D=new double[N];
//Array<double,1> D(N); // for Blitz C++
//vector<double>D(N);
//valarray<double>D(N);
const double a=1.0;
size_t i,j;
for (j=0; j<M; j++)
for (i=0; i<N; i++)
D[i]=a+i+j;
return 0;
}
g++ main.cpp -o main && time main
g++ main.cpp -o main -Ofast && time main
f95 fort.f90 -o fort && time fort
f95 fort.f90 -o fort -Ofast && time fort
Here is statistics:
1) double* D=new double[N]; g++: 58,1s, g++ -Ofast : 16,413s
2) valarrayD(N); ~ the same
3) vector; ~ the same
4) BlitzC++ ; g++ : 3m19,017s, g++ -Ofast : 15,142s
5) ALLOCATE(d(N)); f95 : 42,092s, f95 -Ofast : 0,002s

How to enable C++17 compiling in Visual Studio Community 2019 in a cmake project?

Before posting this question, I have read lots of threads published on StackOverflow. And I still did not find an answer that works.
I have seen that some people saty message is a duplicate, but it is not.
I have checked https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html#prop_tgt:CXX_STANDARD
But i want to apply that to the special case of MSVC, as MSVC is a special case.
I tried that in the out folder :
set_target_properties(myTarget PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
For example, I have read:
How to enable C++17 in CMake
How to enable C++17 compiling in Visual Studio?
But these do not apply to my problem exactly.
Indeed, I recently uninstalled Visual Studio Community 2017, and I have installed Visual Studio Community 2019.
I wanted to compile a code coming from an idea of Bartłomiej Filipek.
The code is below. I used CMake. To the default CMake code, I have added the following:
if (MSVC_VERSION GREATER_EQUAL "1900")
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported)
if (_cpp_latest_flag_supported)
add_compile_options("/std:c++latest")
endif()
endif()
And I have the following compile error:
Erreur C2039 'align_val_t' : not a member of 'std'
So, it means that C++17 is not taken into account.
The version of CMake which is the CMake file by default is indicated by:
cmake_minimum_required (VERSION 3.8)
But on some pages of StackOverflow say that flag is taken into account since CMake VERSION 3.10
However, VSC 19 proposes CMake 3.8
That's quite strange if it is the latest version.
So, how can I definitely solve the problem please?
#include <cstdint>
#include <iostream>
#include <malloc.h>
#include <cassert>
#include <vector>
#include <new>
void* operator new(std::size_t size, std::align_val_t align) {
//#ifdef _MSC_VER
#if defined(_WIN32) || defined(__CYGWIN__)
auto ptr = _aligned_malloc(size, static_cast<std::size_t>(align));
std::cout << "wind" << '\n';
#else
auto ptr = aligned_alloc(static_cast<std::size_t>(align), size);
#endif
if (!ptr)
throw std::bad_alloc{};
std::cout << "new: " << size << ", align: "
<< static_cast<std::size_t>(align)
<< ", ptr: " << ptr << '\n';
return ptr;
}
void operator delete(void* ptr, std::size_t size, std::align_val_t align)
{
std::cout << "avec size delete: " << size << ", align: "
<< static_cast<std::size_t>(align)
<< ", ptr : " << ptr << '\n';
//#ifdef _MSC_VER
#if defined(_WIN32) || defined(__CYGWIN__)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
void operator delete(void* ptr, std::align_val_t align) {
std::cout << "delete: align: "
<< static_cast<std::size_t>(align)
<< ", ptr : " << ptr << '\n';
//#ifdef _MSC_VER
#if defined(_WIN32) || defined(__CYGWIN__)
_aligned_free(ptr);
#else
free(ptr);
#endif
}
//And here’s some test code:
class alignas(32) Vec3dAVX {
double x, y, z;
};
int main() {
std::cout << "std::vector\n";
std::vector<Vec3dAVX> vec;
vec.push_back({});
vec.push_back({});
vec.push_back({});
assert(reinterpret_cast<uintptr_t>(vec.data()) % alignof(Vec3dAVX) == 0);
}
The CMake code:
# CMakeList.txt : fichier projet CMake de niveau supérieur, effectuez une configuration globale
# et incluez les sous-projets ici.
#
cmake_minimum_required (VERSION 3.8)
project ("lameduck")
#Incluez les sous-projets.
add_subdirectory ("lameduck")
if (MSVC_VERSION GREATER_EQUAL "1900")
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("/std:c++latest" _cpp_latest_flag_supported)
if (_cpp_latest_flag_supported)
add_compile_options("/std:c++latest")
endif()
endif()

G++ doesn't find CoInitializeEx (and several other functions)?

I'm trying to compile the following code
#include <iostream>
#include <windows.h>
#include <objbase.h>
int main (int argc, char** argv) {
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr)) {
std::cout << "Initialized" << std::endl;
} else {
std::cout << "Failed" << std::endl;
}
CoUninitialize();
return 0;
}
but
g++ -o test -L"<dir>" -lOle32 <file>.cpp
# <dir> contains Ole32.Lib
always tells me that __imp_CoInitializeEx and __imp_CoUninitialize are undefined and -print-file-name=Ole32.Lib just return Ole32.Lib. If g++ doesn't find Ole32.Lib, maybe
g++ -c -o test.o <file>.cpp
ld -L"<dir>" -lOle32 -o test test.o
works. Now g++/ld actually finds CoInitializeEx and CoUninitialize, but the standard library seems to be missing and adding -static-libstdc++ or -lstdc++ or -llibstdc++ doesn't help either. So what am I missing? Why is g++ unable to find CoInitializeEx and CoUninitialize?
EDIT: I can definitely say that there is nothing wrong with my code, my header files and my library files, because I can compile the code using Visual Studios compiler:
cl /c /EHsc ^
/I"<...>\Microsoft Visual Studio 14.0\VC\include" ^
/I"<...>\Windows Kits\10\Include\<version>\ucrt" ^
/I"<...>\Windows Kits\10\Include\<version>\shared" ^
/I"<...>\Windows Kits\10\Include\<version>\um" ^
/Fotest.obj ^
main.cpp
link /nologo /machine:x64 /subsystem:console ^
/libpath:"<...>\Microsoft Visual Studio 14.0\VC\lib\amd64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\ucrt\x64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\um\x64" ^
/out:test.exe ^
test.obj Ole32.Lib

X11 Include Issues With c++ Via CLion On FreeBSD 11?

I'm using CMake on FreeBSD 11 within CLion and have the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.7)
project(owm)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp owm.cpp owm.h)
add_executable(owm ${SOURCE_FILES})
set(LIBS ${LIBS})
find_package(X11 REQUIRED)
if (X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
link_libraries(${X11_LIBRARIES})
endif(X11_FOUND)
file(GLOB MY_PUBLIC_HEADERS
"test/*"
)
file(COPY ${MY_PUBLIC_HEADERS} DESTINATION test)
Which seems to work fine, however when going to compile the project I get the following:
/usr/local/bin/cmake --build /home/cory/projects/owm/cmake-build-debug --target all -- -j 12
Scanning dependencies of target owm
[ 33%] Building CXX object CMakeFiles/owm.dir/owm.cpp.o
[ 66%] Linking CXX executable owm
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::Create(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)':
/home/cory/projects/owm/owm.cpp:20: undefined reference to `XOpenDisplay'
/home/cory/projects/owm/owm.cpp:22: undefined reference to `XDisplayName'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::owm(_XDisplay*)':
/home/cory/projects/owm/owm.cpp:31: undefined reference to `XInternAtom'
/home/cory/projects/owm/owm.cpp:32: undefined reference to `XInternAtom'
CMakeFiles/owm.dir/owm.cpp.o: In function `owm::~owm()':
/home/cory/projects/owm/owm.cpp:37: undefined reference to `XCloseDisplay'
c++: error: linker command failed with exit code 1 (use -v to see invocation)
gmake[2]: *** [CMakeFiles/owm.dir/build.make:121: owm] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:68: CMakeFiles/owm.dir/all] Error 2
gmake: *** [Makefile:84: all] Error 2
I'm not certain if this is relevant but message(FATAL_ERROR ${X11_LIBRARIES}) returns:
/usr/local/lib/libSM.so/usr/local/lib/libICE.so/usr/local/lib/libX11.so/usr/local/lib/libXext.so
And message(FATAL_ERROR ${X11_INCLUDE_DIR}) returns:
/usr/local/include
Within the offending file I have:
#include "owm.h"
extern "C" {
#include <X11/Xlib.h>
#include <X11/Xutil.h>
}
#include <iostream>
#include <cstring>
#include <algorithm>
template <typename T>
T* CHECK_NOTNULL(T* t) {
if (t == NULL) {
}
return (t);
}
std::unique_ptr<owm> owm::Create(const std::string& display_str) {
const char* display_c_str = (display_str.empty() ? nullptr : display_str.c_str());
Display* display = XOpenDisplay(display_c_str);
if (display == nullptr) {
std::cout << "Failed to open X display " << XDisplayName(display_c_str);
return (nullptr);
}
return (std::unique_ptr<owm>(new owm(display)));
}
owm::owm(Display *display)
: _display(CHECK_NOTNULL(display)),
_root(DefaultRootWindow(_display)),
WM_PROTOCOLS(XInternAtom(_display, "WM_PROTOCOLS", false)),
WM_DELETE_WINDOW(XInternAtom(_display, "WM_DELETE_WINDOW", false)) {
}
owm::~owm() {
XCloseDisplay(_display);
}
void owm::Run() {
}
Command link_libraries affects only on futher executables/libraries. From documentation:
Specify libraries or flags to use when linking any targets created later in the current directory or below by commands such as add_executable() or add_library().
So you need to either:
use link_libraries before add_executable or
use target_link_libraries instead (this is preferred way)

What is missing in the CMakeLists.txt / my library installation?

I reduced my prog to the minimum just to show the pb: cmake does not complain, neither make (running Linux / libglew 1.5 / cmake 2.8.2). The program segfaults, and I have no clue why / which steps I should now make to solve the pb.
Source of render.cpp:
#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/glext.h>
#ifndef WIN32
#include <GL/glx.h>
#endif
#include <iostream>
#include <assert.h>
using namespace std;
int main()
{
cout << "Before init" << endl;
GLenum err = glewInit();
cout << "After init" << endl;
if (err != GLEW_OK)
cout << "Initialization error" << endl;
else{
cout << "Successful init" << endl;
assert(glCreateShader);
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
}
}
The content of CMakeList is:
cmake_minimum_required (VERSION 2.6)
project (render)
IF(CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -std=c++0x")
ENDIF(CMAKE_COMPILER_IS_GNUCC)
# Some directory shortcuts
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/conf)
INCLUDE(FindOpenGL REQUIRED)
INCLUDE(FindGLEW REQUIRED)
INCLUDE_DIRECTORIES(${OPENGL_INCLUDE_DIR})
INCLUDE_DIRECTORIES(${GLEW_INCLUDE_DIR})
message(${OPENGL_LIBRARIES})
message(${GLEW_INCLUDE_DIR})
message(${GLEW_LIBRARIES})
add_executable(render render.cpp)
target_link_libraries(render ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES})
As mentioned, it compiles and segfaults at the call to glewInit(). I have no idea what to search for at this point..
Any help would be great,
Thanks
Might be useful to anyone, I solved it: using openGL, you need to create a context before being able to call glewInit(). This can be done using the SDL library (simplifies this task). Have a look at this tutorial.