Question

I have a template class foo

template <typename Item>
class foo
{
    void method()
    {
        // ...
    }
}

what I need is to change the implementation of the method, based on the type Item, based if a function say unsigned int hasher(const Item& item) exists.

My question is - how is this technically possible and if not how I could organize the code to have this?

Note the performance is a big deal for the algorithm and I am looking for solutions that will allow the compilers to solve the difference compile time.

Was it helpful?

Solution

You need to apply template policies, take a look at: http://en.wikipedia.org/wiki/Policy-based_design also C++ templates

OTHER TIPS

Haven't touched c++ code for years now so can't write you an example on the spot [well maybe I could but the results would be hilarious] but as pointed out in this answer the powers you seek can be found in SFINAE

// Macro helper to create traits
#define HAS_TEMPLATED_FUNC(traitsName, funcName, Prototype)                          \
    namespace detail {                                                               \
    template<typename U>                                                             \
    class traitsName                                                                 \
    {                                                                                \
        typedef std::uint8_t yes;                                                    \
        typedef std::uint16_t no;                                                    \
        template <typename T, T> struct type_check;                                  \
        template <typename T = U> static yes &chk(type_check<Prototype, &funcName>*); \
        template <typename > static no &chk(...);                                    \
    public:                                                                          \
        static bool const value = sizeof(chk<U>(0)) == sizeof(yes);                  \
    };                                                                               \
    }                                                                                \
    template <typename U>                                                            \
    struct traitsName : std::conditional<detail::traitsName<U>::value,               \
                                         std::true_type, std::false_type>::type {}

Now assume that:

unsigned int hasher(const int& item);

Now create the trait:

HAS_TEMPLATED_FUNC(has_hasher, hasher, unsigned int (*)(const T&));

// some test.
static_assert(has_hasher<int>::value, "");
static_assert(!has_hasher<char>::value, "");

Now, there is some way to use it

Tag dispatching:

template <typename Item>
class foo
{
public:
    void method()
    {
        method(has_hasher<Item>());
    }
private:
    void method(std::true_type)
    {
        // You may use hasher here.
        hasher(Item{});
    }
    void method(std::false_type)
    {
        // You cannot use hasher here.
    }
};

or SFINAE:

template <typename Item>
class foo
{
public:
    template <typename T = Item>
    typename std::enable_if<has_hasher<T>::value, void>::type
    method()
    {
        // You may use hasher here.
        hasher(Item{});
    }

    template <typename T = Item>
    typename std::enable_if<!has_hasher<T>::value, void>::type
    method()
    {
        // You cannot use hasher here.
    }
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top