Question

I've implemented a policy-based class. For the moment, the class template and its policy classes are declared in a namespace called utility.

The problem I face is the verbosity of the resulting code. Client code looks like that:

utility::MyTool<utility::AFirstPolicy, utility::ASecondPolicy>
my_function(utility::MyTool<utility::AnotherFirstPolicy, utility::AnotherSecondPolicy>);

Not very readable, as you can see. I would like to get something closer from:

MyTool<AFirstPolicy, ASecondPolicy>
my_function(MyTool<AnotherFirstPolicy, AnotherSecondPolicy>);

I'm wondering what the good practice is in such a case. Here is what I can think of:

Typedef

The most obvious solution. Not very convenient for me because the policies can differ from function to function an bring important information on the function usage. I would like them to appear directly in the function prototype. Moreover, it introduces many type names in several namespaces.

Using directive

Put a using namespace utility; or using utility::MyTool; using utility::AFirstPolicy;, etc. in my file.

The tool is often used in header files from other namespaces, which makes using-directives not very suitable.

Policy classes in global namespace

I don't like this approach especially as policy classes often have vague names that make sense only in their context.

Macro

Use something as

#define MY_TOOL(pcy1, pcy2) utility::MyTool<utility::##pcy1, utility::##pcy2>

to transform the previous code to

MY_TOOL(AFirstPolicy, ASecondPolicy)
my_function(MY_TOOL(AnotherFirstPolicy, AnotherSecondPolicy));

I'm not sure this is more readable. It works only for a fixed number of policies (this is my case: always 2, no default setting) and it does not work if the policy classes themselves take template parameters.

Which of the previous approaches would you recommend to me? Are there "best practices"? Another idea?

Était-ce utile?

La solution

If you have a my_function(utility::MyTool<...>), then I would say that my_function belongs to the interface of the class template utility::MyTool<...>. In other words, my_function itself belongs to the namespace utility.

This means that you can write code in the desired shorthand form:

namespace utility {   
    typedef MyTool<AFirstPolicy, ASecondPolicy> SomeTool;
    my_function(SomeTool);    
}

You can read more about interfaces and namespaces in this old column "What's In a Class" by Herb Sutter.

Note that even if you want to use functions in other namespaces with classes from namespace utility, you can still reopen that namespace and define the policy class right there and do something like

// SomeHeader.hpp
namespace bla {
   // your classes and functions
}

// reopen namespace utility
namespace utility {   
    typedef MyTool<AFirstPolicy, ASecondPolicy> SomeTool;
}

namespace bla {
    typedef utility::SomeTool BlaTool; // or using-declaration
    my_function(BlaTool);
}

This is of course more verbose than defining my_function inside the utility namespace, but at least you can assemble all the various policies without too much typing.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top