Search code examples
c++trompeloeil

Trompeloeil MAKE_MOCK0 with a template as a return type


When using Trompeloeil to mock unit tests in C++, how can use an unordered_map as a return type?

// This example works fine
// return type is void, my_function takes no arguments 
MAKE_MOCK0(my_function, void(), override);


// This is what I'm trying to do but fails
MAKE_MOCK0(my_function, std::unordered_map<std::string, int>(), override);

Visual Studio is giving the following IntelliSense errors,

  • C2976 - std::unordered_map: too few template arguments
  • C2955 - std::unordered_map: use of class template requires template argument list
  • C2923 - trompeloeil::param_list: std::_Hash<_Traits::size> is not a valid template type argument for parameter type T
  • C2143 - syntax error missing > before ;
  • C2955 - trompeloeil::param_list use of class template requires template argument list
  • C2338 - function signature does not have 0 parameters
  • C3203 - unordered_map unspecialized class can't be used as a template argument for template parameter 'Sig', expected a real type
  • C4346 - std::unordered_map::type dependent name is not a type
  • C2923 - trompeloeil::identity_type: std::unordered_map::type is not a valid template type argument for parameter type T
  • C3203 - unordered_map unspecialized class can't be used as a template argument for template parameter 'T', expected a real type

Solution

  • Templated return types need to be wrapped in (...). This is explained in: Q. Why can't I mock a function that returns a template?

    // Bad
    MAKE_MOCK0(my_function, std::unordered_map<std::string, int>(), override);
    
    // Good
    MAKE_MOCK0(my_function, (std::unordered_map<std::string, int>()), override);
    

    The C++ preprocessor may have an issue parsing the template with multiple parameters std::string, int. If this occurs, moving the return type to a typedef can help. https://stackoverflow.com/a/38030161/2601293

    typedef std::unordered_map<std::string, int> My_Type;
    ...
    MAKE_MOCK0(my_function, (My_Type()), override);