GTest fixture when constructor takes parameters? - c++

I have a simple example class. It has one data member, which is a std::vector of pointers to armadillo matrices. the constructor takes such a vector as the only argument. here's file TClass.cpp:
#include <armadillo>
#include <vector>
class TClass {
private:
std::vector<arma::mat * > mats;
public:
TClass(std::vector<arma::mat * > m_);
arma::mat * GetM( int which ){ return( mats.at(which) );};
};
TClass::TClass(std::vector<arma::mat * > m_){
mats = m_;
}
I want to construct a GTest fixture to test member function GetM. Here is what I have done:
#include <gtest/gtest.h>
#include "TClass.cpp"
class TClassTest : public ::testing::Test {
protected:
int n;
int m;
std::vector<arma::mat * > M;
virtual void SetUp() {
n = 3;
m = 2;
arma::mat M1 = arma::randu<arma::mat>(n,m);
arma::mat M2 = arma::randu<arma::mat>(n,m);
M.push_back( &M1);
M.push_back( &M2);
}
// virtual void TearDown() {}
// initiate a TClass object
TClass T(M);
};
// my test
TEST_F(TClassTest, CanGetM1){
EXPECT_EQ( T.GetM(0), M.at(0) );
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I compile this with g++ TClassTest.cpp -o tclass -larmadillo. It tells me that TClassTest.cpp:24: error: ‘M’ is not a type. I dont' understand why I cannot construct the TClass object in the fixture definition?

The object T cannot be initialized in the declaration of class TClassTest. Have you been writing Java lately? ;-)
To initialize it, you can do something like this:
class TClassTest : public ::testing::Test {
// ... (rest of code is fine as is)
virtual void SetUp() {
// ...
T = new TClass(M);
}
virtual void TearDown() { delete T; }
TClass *T;
};

Related

How to pass smart pointer instead of "this" in C++ 11?

I am using c++11 compiler.
I have two classes - class Test and class TestHelper.
The class Test is a friend-to-class TestHelper.
The class Test is only which we can access from outside.
Now, we want to call Test API i.e. setVal(). This setVal() should call
Test2 API i.e. setX and is expecting this pointer. I don't want to use this pointer but want
to use a smart pointer instead. How can I do so?
The notion of this kind of desirability is because of the fact that in reality, my class Test is pretty big. So, I am trying to make a helper class for Test i.e.
class TestHelper;
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(this, 324);
}
};
class TestHelper
{
public:
void setX(Test *test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
};
int main()
{
std::cout << "Hello World!\n";
Test x;
x.setVal(130);
}
I tried changing the prototype from void setX(Test *test, int val)
to void setX(std::shared_ptr<Test> test, int val) but don't know how to pass this pointer
as std::shared_ptr<Test> test here.
So here is working solution with shared pointers. The example doesn't even compile due to missing definitions so you have to restructure your code into headers and cpp files.
Test.h:
#ifndef TEST_H
#define TEST_H
#include <memory>
#include "TestHelper.h"
class Test : public std::enable_shared_from_this<Test>
{
private:
friend class TestHelper;
int x;
public:
void display();
void setVal(int val);
};
#endif
Test.cpp:
#include <iostream>
#include "Test.h"
void Test::display() {
std::cout << x;
}
void Test::setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
TestHelper.h:
#ifndef TESTHELPER_H
#define TESTHELPER_H
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
#endif
TestHelper.cpp:
#include <memory>
#include "TestHelper.h"
#include "Test.h"
void TestHelper::setX(std::shared_ptr<Test> test, int val) {
/** some algorithm here and then change val to something else */
test->x = val*100;
}
main.cpp:
#include <iostream>
#include <memory>
#include "Test.h"
int main(void){
std::cout << "Hello World!\n";
auto x = std::make_shared<Test>();
x->setVal(130);
x->display();
}
You can run it here: https://paiza.io/projects/e/79dehCx0RRAG4so-sVZcQw
I don't understand why you want this, here's a few variants that compile
reference
// Reference variant
#include <iostream>
class Test;
class TestHelper
{
public:
void setX(Test & test, int val);
};
class Test
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(*this, 324);
}
};
void TestHelper::setX(Test &test, int val)
{
/** some algorithm here and then change val to something else */
test.x = val*100;
}
int main()
{
Test x;
x.setVal(130);
x.display();
}
http://cpp.sh/7t3ec
shared ptr
// Shared ptr variant
#include <iostream>
#include <memory> // Required for shared_ptrs
class Test;
class TestHelper
{
public:
void setX(std::shared_ptr<Test> test, int val);
};
class Test : public std::enable_shared_from_this<Test>
{
friend class TestHelper;
int x;
public:
void display() {
std::cout << x;
}
void setVal(int val) {
TestHelper testH;
testH.setX(shared_from_this(), 324);
}
};
void TestHelper::setX(std::shared_ptr<Test> test, int val)
{
/** some algorithm here and then change val to something else */
test->x = val*100;
}
int main()
{
auto x = std::make_shared<Test>(); // x needs to be created as shared_ptr or it won't work
x->setVal(130);
x->display();
}
http://cpp.sh/87ao2
Perhaps with these you can refine your question?

Even after macro substitution can't resolve the variable

I am trying to learn gtest. I have my class Calculator that I want to test.
#pragma once
// whattotest.cpp
#include <math.h>
class Calculator{
public:
double squareRoot(const double a) {
double b = sqrt(a);
if(b != b) { // nan check
return -1.0;
}else{
return sqrt(a);
}
}
double add (const double a, const double b){
return (a + b);
}
double multiply(const double a, const double b){
return (a * b);
}
};
I have the test class code below.
#include "gtest_example.hpp"
#include <gtest/gtest.h>
using namespace std;
class CalculatorTest : public ::testing::Test {
protected:
virtual void SetUp() {
calc = new Calculator();
}
virtual void TearDown() {
delete calc;
}
Calculator *calc;
};
TEST(CalculatorTest, ShouldReturnSum) {
SetUp();
ASSERT_EQ(72, calc->add(36.0, 36.0));
}
TEST(CalculatorTest, ShouldReturnProduct) {
SetUp();
ASSERT_EQ(36, calc.multiply(6.0, 6.0));
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
In both the ASSERT_EQ lines I get the following errors.
Even after macro substitution can't resolve the variable calc.
What am I doing wrong hee.
As you use fixture, you should use macro TEST_F instead of TEST.
class CalculatorTest : public ::testing::Test {
Calculator calc;
};
TEST_F(CalculatorTest, ShouldReturnSum)
{
ASSERT_EQ(72, calc.add(36.0, 36.0));
}
TEST_F(CalculatorTest, ShouldReturnProduct)
{
ASSERT_EQ(36, calc.multiply(6.0, 6.0));
}
Without fixture, you might simply do:
TEST(CalculatorTest, ShouldReturnSum)
{
Calculator calc;
ASSERT_EQ(72, calc.add(36.0, 36.0));
}
TEST(CalculatorTest, ShouldReturnProduct)
{
Calculator calc;
ASSERT_EQ(36, calc.multiply(6.0, 6.0));
}

C2440 cannot convert from 'void (_cdecl*)(int)' to 'void(_cdecl&)(int)

I am using C++ in native mode with Visual Studio 2017 and I am trying to compile and run the example code found at Debugging a Parallel Application in Visual Studio.
For the record, I program in C not C++. I am clueless when it comes to method declarations (among many other things). I suspect correcting the error is simple but, I simply don't know how.
In other words, I am currently RTFineM. I simply copied and pasted the example given in the url above and ran into 2 problems. First it complained about something being deprecated but a simple define took care of that problem. Second it complained about not being able to convert a type into another as stated in the title.
The RunFunc class causing the problem is declared as follows:
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
My question/request is: how does the declaration of RunFunc need to be in order for the example to compile and run properly ?
Thank you, much appreciate the help.
In this constructor
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
the prameter Func func is adjusted by the compiler to the type Func *func. On the other hand the data member m_Func is declared as a referenced type.
Func& m_Func;
And the error message says about incompatibility of the types.
C2440 cannot convert from 'void (_cdecl*)(int)' to 'void(_cdecl&)(int)
Try to declare the constructor like
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
Or declare the data member like
Func *m_Func;
without changing the constructor.
Here are two demonstrative programs
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
and
#include <iostream>
typedef void Func( int );
class RunFunc
{
Func *m_Func;
int m_o;
public:
RunFunc(Func func,int o):m_Func(func),m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
return 0;
}
In your code you are tyring to bound a reference to a temporary, namely to copy of argument passed to the constructor. You can try to run the following code snippet to see the difference:
struct Func {
int _i;
void operator()(int i) { cout << i*_i << endl; }
};
class RunFunc
{
Func& m_Func;
int m_o;
public:
RunFunc(Func &func, int o) :m_Func(func), m_o(o)
// RunFunc(Func func, int o) :m_Func(func), m_o(o)
{
};
void operator()()const
{
m_Func(m_o);
};
};
int main() {
Func f{ 5 };
RunFunc rf(f, 2);
rf();
return 0;
}
This is a legacy approach. You can use standard library functor and binder instead. For example:
#include <functional>
#include <iostream>
static void my_callback(int i) {
std::cout<< i << std::endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::function<void()> functor;
functor = std::bind(my_callback, 1);
functor();
return 0;
}

Call member function of an object using pthread

How can I call the thread_ready_function into a thread as commented, using pthread ? I need to call it with the class object (In the real world the function uses attributes previously set).
MWE
#include <iostream>
#include <pthread.h>
class ClassA
{
public:
void * thread_ready_function(void *arg)
{
std::cout<<"From the thread"<<std::endl;
pthread_exit((void*)NULL);
}
};
class ClassB
{
ClassA *my_A_object;
public:
void test(){
my_A_object = new ClassA();
my_A_object->thread_ready_function(NULL);
// my_A_object->thread_ready_function(NULL);
// ^
// I want to make that call into a thread.
/* Thread */
/*
pthread_t th;
void * th_rtn_val;
pthread_create(&th, NULL, my_A_object.thread_ready_function, NULL);
pthread_join(th, &th_rtn_val);
*/
}
};
int main()
{
ClassB *my_B_object = new ClassB();
my_B_object->test();
return 0;
}
if you don't want to use C++11 or stl or boost, you must use the static key word for your member function,so that the pthread can call your member function!
example code:
#include <iostream>
#include <pthread.h>
using namespace std;
class A{
public:
static void* thread(void* args);
int parella_thread(int thread_num);
};
void* A::thread(void* args)
{
cout<<"hello world"<<endl;
}
int A::parella_thread(int thread_num)
{
pthread_t* thread_ids = new pthread_t[thread_num];
for(int i=0;i<thread_num;i++)
{
pthread_create(&thread_ids[i],NULL,thread,(void*)NULL);
}
delete[] thread_ids;
}
int main(int argc,char*argv[])
{
A test;
test.parella_thread(4);
return 0;
}

How to use c++ std complex numbers in QtScript

I try to find out how to use complex numbers in QtScripts such that slots defined with complex arguments can be called from a QtScript. Also basic algebra (+,-,exp, ... ) of complex-numbers should be accessible to the user from the script.
Just for illustration want I want to call is:
#include<complex>
typedef complex<double> Complex;
class MyCppClass : public QObject
{
Q_OBJECT
public:
...
public slots:
void mySignal(Complex rCValue); !! <<== should be callable from QtScript
...
}
Any ideas? Thx!
I think you must implement complex algebra in QtScript (something like http://examples.oreilly.com/9781565923928/text/8-6.txt) and then modify mySignal to accept an object like this.
It's not the final answer ... since as indicated above the operators +,- and * cannot be used for Complex quantities on the javascript side. But for those interested I'd like to share the following code pieces, which allow to trigger slots with complex arguments.
test.h:
#include <QtCore>
#include <QtScript>
#include <complex>
#include <iostream>
using namespace std;
typedef complex<double> Complex;
Q_DECLARE_METATYPE(Complex)
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass() : QObject() {};
public slots:
void TestOutput(Complex rValue);
};
test.cpp:
#include "test.h"
void TestClass::TestOutput(Complex rValue)
{
cout << "received value "<< rValue << endl;
}
main.cpp:
#include "test.h"
QScriptValue toScriptValue(QScriptEngine *eng, const Complex& rValue)
{
QScriptValue obj = eng->newObject();
obj.setProperty("re",real(rValue));
obj.setProperty("im",imag(rValue));
return obj;
}
void fromScriptValue(const QScriptValue &obj, Complex& rValue)
{
double re=obj.property("re").toNumber();
double im=obj.property("im").toNumber();
rValue=Complex(re,im);
}
QScriptValue constructComplex(QScriptContext *context, QScriptEngine *engine)
{
Complex complex=Complex(2,1);
return engine->toScriptValue(complex);
}
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QScriptEngine eng;
// register our custom type
qScriptRegisterMetaType<Complex>(&eng, toScriptValue, fromScriptValue);
TestClass *test=new TestClass;
QObject *someObject = (QObject*)test;
QScriptValue objectValue = eng.newQObject(someObject);
eng.globalObject().setProperty("myObject", objectValue);
QScriptValue val = eng.evaluate("function Complex(real, imaginary) { this.re = real; this.im = imaginary;}; cadd = function (a, b) {return new Complex(a.re + b.re, a.im + b.im);};");
val = eng.evaluate("my_complex=new Complex(8,1); my_comp=new Complex(2,9); my_c=cadd(my_comp,my_complex);");
cout << "script"<< val.toString().toStdString() << endl;
Complex cval = qscriptvalue_cast<Complex>(val);
cout << "qscriptvalue_cast : "<< cval << endl;
val = eng.evaluate("myObject.TestOutput(my_c)");
return 0;
}