C++ Functor

Dustin Morris
2 min readApr 21, 2023

I tend to write about things that I find interesting when I code. Today’s interesting topic is c++ functors. I recently was writing some unit tests using Microsoft::VisualStudio::CppUnitTestFramework.

The CppUnitTestFramework has an Assertion library. The code I was working on I expected an exception to be thrown. The Assert::ExpectedException() is defined as below:

template<typename _EXPECTEDEXCEPTION, typename _FUNCTOR>
static void Assert::ExpectException(
_FUNCTOR functor,
const wchar_t* message= NULL,
const __LineInfo* pLineInfo= NULL)

The only required parameters being the type name of the expected exception and a FUNCTOR.

For my tests, I defined the functor in 2 different ways because of different needs in different test files. One with a lambda expression and one with a functor class definition. My lambda expression looks like this:

        auto functor = [&, coolVariable, coolObject]
{
try
{
coolObject.coolFunction(coolVariable);
}
catch (...)
{
throw std::invalid_argument("invalid");
}
};

Assert::ExpectException<std::invalid_argument>(functor, L"Failed to throw invalid argument exception.");

I was working with some pretty old c++ code and just wanted to make sure I captured an exception defined the way I knew it would be defined. The auto definition here captures the functor passed into Assert::ExpectException(functor). Assert::ExpectException then invokes the function defined by the functor. Internal code of the Assert::ExpectException function will throw an exception to the test for any exception caught that is NOT the expected exception and additionally throws an exception if NO exception is caught.

The lambda function was perfect for the single test I needed it for in my first test file. However, in my second test file, I had several tests that needed to invoke the same functor with different parameters. Writing several lambdas would clutter the code. I instead opted for a Functor class.

class CreateFunctor
{
private:
int cc;
unsigned int size;
public:
CreateFunctor(int cc, unsigned int size) : cc(cc), size(size) {}

void operator()() const
{
try
{
MyCoolTestMethod(cc, size);
}
catch (...)
{
throw std::invalid_argument("invalid");
}
}
};

TEST_CLASS(MyCoolTests)
{
public:
TEST_METHOD(MyCoolTestMethod)
{
Assert::ExpectException<std::invalid_argument>(CreateFunctor(cc, UINT32_MAX), L"Failed to throw invalid argument exception.");
}
}

In the functor class, the operator() is overloaded. The code I want executed by the Assert::ExpectException method is contained within this operator() overload. Where as the () in the CreateFunctor(cc, UINT32_MAX) is used to instantiated the CreateFunctor object with the values cc and UINT32_MAX. Again the Assert function invokes the functor but this time with the overloaded () and performs the exact same steps as the lambda function did.

I hope you find this as interesting as I did.

--

--