Code duplication between typedefs and explicit ins

2019-02-10 04:52发布

问题:

tree.h

template<typename Functor, char Operator>
class binary_operation : public node
{
// ... unimportant details ...

    unsigned evaluate() const;
    void print(std::ostream& os) const;
};

typedef binary_operation<std::plus<unsigned>, '+'> addition;
typedef binary_operation<std::multiplies<unsigned>, '*'> multiplication;
// ...

tree.cpp

template<typename Functor, char Operator>
unsigned binary_operation<Functor, Operator>::evaluate() const
{
    // ... unimportant details ...
}

template<typename Functor, char Operator>
void binary_operation<Functor, Operator>::print(std::ostream& os) const
{
    // ... unimportant details ...
}

template class binary_operation<std::plus<unsigned>, '+'>;
template class binary_operation<std::multiplies<unsigned>, '*'>;
// ...

As you can see, there is some code duplication between the typedefs in the header file and the explicit class template instantiations in the implementation file. Is there some way to get rid of the duplication that does not require putting "everything" in the header file as usual?

回答1:

This is invalid and rejected by implementations because a typedef name is used in the elaborated type specifier

template class addition;

The following is invalid too, because the Standard says that there must be a simple template id contained in the elaborated type specifier. Comeau online and GCC both accept it, though.

template class addition::binary_operation;

You could apply a pervert workaround though to be fully Standards compliant

template<typename T> using alias = T;
template class alias<multiplication>::binary_operation;

At least I could not find it being invalid anymore on a quick glance over the spec.



回答2:

Use a macro. You could write a header like

I_HATE_MACROS(binary_operation<std::plus<unsigned>, '+'>, addition)
I_HATE_MACROS(binary_operation<std::multiplies<unsigned>, '*'>, multiplication)

Then you can do

#define I_HATE_MACROS(a, b) typedef a b;

Or

#define I_HATE_MACROS(a, b) template class a;

Then

#include "DisgustingMacroHackery.h"


回答3:

I ask my self, why do you actually write a .cpp file as you have templates and they should go either all in the header file or in a seprarate file e.g ".icc", which holds the stuff from the cpp file. I am not sure but tempalates definitions should always NOT be in a compilation unit.

See -> Storing C++ template function definitions in a .CPP file