My tests are contained within functions declared with TEST_F so that I can use a new test fixture object between tests. For each TEST_F, a new instance of the test fixture is created. But what if I wish to loop over an enum in my test and have a new instance of the test fixture for each iteration? What should I do in this case?
It sounds like you want to use value-parameterized tests.
You could iterate through the values of an enum like this:
#include <iostream>
#include "gtest/gtest.h"
enum Malt { bowmore = 10, talisker, scapa };
class Whisky {
public:
explicit Whisky(const Malt& malt) : malt_(malt) {}
bool IsIslay() const { return malt_ == bowmore; }
private:
Malt malt_;
};
class DramTest : public testing::TestWithParam<Malt> {
protected:
DramTest() : whisky_(GetParam()) {}
Whisky whisky_;
};
TEST_P(DramTest, IsIslay) {
if (GetParam() == bowmore)
EXPECT_TRUE(whisky_.IsIslay());
else
EXPECT_FALSE(whisky_.IsIslay());
}
INSTANTIATE_TEST_CASE_P(AllMalts, DramTest,
testing::Values(bowmore, talisker, scapa));
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
If you have a large number of enum values, you could use the Range generator instead of the Value one:
testing::Range<int>(bowmore, scapa + 1)
but this needs some casting in the fixture between ints and the enum type.
Both options suffer from maintenance problems; if you add a new enum value, you need to remember to change the test.
Related
//MyWrapper.h
#include "arithmetic.h"
#include "mathematics.h"
namespace MyWrapper {
public ref class ClassA
{
public:
ClassA();
~ClassA();
int add(int, int);
private:
MyEngine::Arithmetic *nativeClassA;
}
public ref class ClassB
{
public:
ClassB(ClassA^ arith);
~ClassB();
int pow(int, int);
private:
MyEngine::Mathematics *nativeClassB;
}
}
//MyWrapper.cpp
#include "MyWrapper.h"
My::ClassA::ClassA()
{
nativeClassA = new MyEngine::Arithmetic();
}
My::ClassA::~ClassA()
{
delete nativeClassA;
}
int My::ClassA::add(int a, int b)
{
return nativeClassA->add(a, b);
}
My::ClassB::ClassB(ClassA^ classA)
{
nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); //***Error***
}
My::ClassB::~ClassB()
{
delete nativeClassB;
}
int My::ClassB::pow(int a, int b)
{
int result = nativeClassB->pow(a, b);
return result;
}
Here, Mathematics class need to init with Arithmetic class.
But nativeClassA is private variable in ClassA.
So nativeClassB = new MyEngine::Mathematics(classA->nativeClassA); , it will occurs compile error.
So I changed the nativeClassA to public.
But at that time, nativeClassA will export to c#.
I don't want to export nativeClassA variable to c#.
How can I fix it?
Thanks in advice.
Since you're writing a managed class, you can use all the access modifiers that C# has. This seems like a perfect scenario for internal. (The linked documentation is for C#, but it's the same keyword in C++/CLI.)
Is it possible to serialize std::chrono::duration or especially std::chrono::milliseconds with boost::serialization?
The following error occurred:
"struct std::chrono::duration >’ has no member named ‘serialize"
I need this for my template-class:
#include <iostream>
#include <chrono>
#include <boost/serialization/serialization.hpp>
template<typename T>
class Field {
public:
// Default Constructor
Field() {}
Field(std::string name, T value) :
mName(name), mValue(value) {}
~Field() {}
const std::string& getName() const {
return mName;
}
T getValue() const {
return mValue;
}
private:
friend class boost::serialization::access;
template<typename Archive>
void serialize(Archive& archive, const unsigned int) {
archive & boost::serialization::make_nvp("Name", mName);
archive & boost::serialization::make_nvp("Value", mValue);
}
std::string mName;
T mValue;
};
BOOST_CLASS_IMPLEMENTATION( Field<int>, boost::serialization::object_serializable )
BOOST_CLASS_IMPLEMENTATION( Field<std::chrono::milliseconds>, boost::serialization::object_serializable )
I'm creating the following object:
Field<std::chrono::milliseconds> mSimTime;
Let's say you have:
auto earlier = std::chrono::system_clock::now();
auto now = std::chrono::system_clock::now();
auto aLotOfMilliseconds= std::chrono::duration_cast<std::chrono::milliseconds>(
now - earlier);
// Serialize here int64_t.
then after deserialization, you have:
std::chrono::duration<int64_t, std::milli> duration(aLotOfMilliseconds);
I'm attempting to make some of our IJW wrappers between our C++ and our .NET code easier to use.
The following is a test situation with our wrapper platform:
// NativeWrapper.h
#pragma once
template <class T>
public ref class NativeWrapper
{
public:
// ...
operator T* ();
operator T& ();
// ...
};
// Test.h
#pragma once
class Test { /* ... */ };
#pragma make_public( Test )
// TestN.h
#pragma once
#include "NativeWrapper.h"
#include "Test.h"
public ref class TestN : public NativeWrapper<Test>
{ /* ... */ };
// main.cpp
#include "TestN.h"
void f(const Test&) { /* ... */ }
int main()
{
TestN^ t = gcnew TestN();
f(t);
return 0;
}
The implicit cast from TestN^ to const Test& via the user-defined operator Test&() works just fine, as I had expected.
However, when I try this in my production code, something is different. It cannot find the proper conversion. I must do the following:
f((Test&)t);
I haven't been able to identify any fundamental differences between what I'm doing in my test and what I'm doing in the main codebase. The NativeWrapper template is identical.
What types of situations might cause the compiler to fail to use a non-const conversion operator when the only acceptable type is the const reference type?
Thanks.
Such as mfc, it should add
DECLARE_SERIAL(CGraph)
If I a have a class,
class A
{
int a,b;
};
I can store the value of a and b to a file ,then read it.
So I couldn't understand why DECLARE_SERIAL(CGraph) used.
The DECLARE_SERIAL and IMPLEMENT_SERIAL macros are only necessary for classes derived from CObject that you wish to serialize polymorphically using the framework provided by MFC.
If your class is not derived from CObject and/or you do not wish to use MFC's serialization polymorphically (i.e. via a pointer to CObject), then of course you can implement your own solution as you rightly say.
For example, DECLARE_SERIAL(CMyClass) expands to the following code that goes in your class declaration
protected:
static CRuntimeClass* __stdcall _GetBaseClass();
public:
static CRuntimeClass classCMyClass;
static CRuntimeClass* __stdcall GetThisClass();
virtual CRuntimeClass* GetRuntimeClass() const;
static CObject* __stdcall CreateObject();
friend CArchive& __stdcall operator>>(CArchive& ar, CMyClass* &pOb);
and IMPLEMENT_SERIAL(CMyClass, CObject, VERSIONABLE_SCHEMA | 1) expands to the following code that goes in the cpp file
CObject* __stdcall CMyClass::CreateObject()
{
return new CMyClass;
}
extern AFX_CLASSINIT _init_CMyClass;
CRuntimeClass* __stdcall CMyClass::_GetBaseClass()
{
return (CObject::GetThisClass());
}
__declspec(selectany) CRuntimeClass CMyClass::classCMyClass =
{
"CMyClass", sizeof(class CMyClass), (0x80000000) | 1,
CMyClass::CreateObject, &CMyClass::_GetBaseClass, 0, &_init_CMyClass
};
CRuntimeClass* __stdcall CMyClass::GetThisClass()
{
return ((CRuntimeClass*)(&CMyClass::classCMyClass));
}
CRuntimeClass* CMyClass::GetRuntimeClass() const
{
return ((CRuntimeClass*)(&CMyClass::classCMyClass));
}
AFX_CLASSINIT _init_CMyClass((CMyClass::GetThisClass()));
CArchive& __stdcall operator>>(CArchive& ar, CMyClass* &pOb)
{
pOb = (CMyClass*) ar.ReadObject((CMyClass::GetThisClass()));
return ar;
}
As it says in MSDN it is also possible to use serialization without using the above macros:
I have spotted something like this in code:
void foo(IList<int>^ const & list ) { ... }
What does this ^ const& mean? I looked in the C++/CLI specification, but found no comments on making constant tracking references, nor the ^& combo.
Is this legal?
This code was probably written by a C++ programmer that used common C++ idiom to write C++/CLI. It is quite wrong, passing a reference to tracking handle is only possible if the handle is stored on the stack. It cannot work if the passed List<> reference is stored in a field of an object on the heap, the garbage collector can move it and make the pointer invalid. The compiler will catch it and generate an error. The ^ is already a reference, no additional reference is needed.
Without the reference, the const keyword doesn't make a lot of sense anymore either. Not that it ever did before, the CLR cannot enforce it. Not that this mattered much here, this code could not be called from any other .NET language. They won't generate a pointer to the tracking handle.
Just fix it, there's little point in keeping bad code like this:
void foo(IList<int>^ list ) { ... }
Example of code that shows that the reference cannot work:
using namespace System;
using namespace System::Collections::Generic;
ref class Test {
public:
IList<int>^ lst;
void foo(IList<int> const &list) {}
void wontcompile() {
foo(lst); // C3699
IList<int>^ okay;
foo(okay);
}
};
It's a reference which is constant to a tracking handle.
It allows you to pass the handle by reference instead of by value. Presumably the author thinks it's more efficient than copying the handle.
If the author meant to make the handle constant he should have used either of
Method(TestClass const ^ const & parameter)
Method(TestClass const^ parameter)
Or alternatively
Method(TestClass const^& parameter) - but the caller must const up the handle first
with
TestClass const^ constHandle = nonConstHandle
An example of each:
// test.cpp : Defines the entry point for the console application.
#include "stdafx.h"
ref class TestClass
{
public:
void setA(int value)
{
a = value;
}
TestClass() :
a(10)
{
}
private:
int a;
};
class TakesHandle
{
public:
void methodX1(TestClass const ^ const & parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX2(TestClass const^ parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
void methodX3(TestClass const^& parameter)
{
// Un-commenting below causes compiler error
// parameter->setA(11);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TakesHandle takes;
TestClass ^ test1 = gcnew TestClass();
// compiles
takes.methodX1(test1);
// compiles
takes.methodX2(test1);
TestClass const ^ constHandle = test1;
takes.methodX3(constHandle);
return 0;
}