samedi 27 juin 2015

Pass member template function with unknown signature and possibly overloaded to template

I'm writing a template to extract the return type of a member function with a specific signature. I need this in order to create a type_trait that verifies some constraints on this type, so that I can enable_if certain optimizations if I can use them. At the moment I have this code, which seems to work fine:

#include <iostream>
#include <type_traits>

struct A {
    const double & foo(size_t i) const;
    const int & foo(size_t i);
};

struct B {
    const double & foo(size_t i);
    size_t bar() const;
};

struct C {
};

template <typename T>
struct remove_cv_ref { using type = typename std::remove_cv<typename std::remove_reference<T>::type>::type; };

template <typename Q, typename R, typename ...Args>
auto extractor(R (Q::*)(Args...),       Args &&...) -> R;

template <typename Z> auto fooRetType(Z* z) ->
    // Here I select the function name and its arguments
    typename remove_cv_ref<decltype(z->foo(std::declval<size_t>()))>::type;

// Fallback, returns whatever type
template <typename Z> auto fooRetType(...) -> int;

template <typename M>
// Here I can select between const and non-const versions
// (currently const)
using K = decltype(fooRetType<const M>(0)); 

int main() {
    // Here only A has a foo(size_t) const, so it's the only
    // one that matches.
    K<A> testA;
    std::cout << "Is double? " << std::is_same<double, decltype(testA)>::value << "\n";

    K<B> testB;
    std::cout << "Is double? " << std::is_same<double, decltype(testB)>::value << "\n";

    K<C> testC;
    std::cout << "Is double? " << std::is_same<double, decltype(testC)>::value << "\n";

    return 0;
}

While I can easily select between const and non-const versions of the method by changing the type I pass to fooRetType, I'd love to be able to also pass to it the name of the functions and its argument signature.

Is it possible to do something like this (bonus if it's without macros), or am I stuck with creating a pair of functions for every signature I want to check?

Aucun commentaire:

Enregistrer un commentaire