Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can you detect template member of a class using std::is_detected

I use std::experimental::is_detected to determine if class has certain member functions:

#include <utility>
#include <experimental/type_traits>

template<typename USC>
class Descriptor
{
private:

    template<class T>
    using has_member1_t = 
        decltype(std::declval<T>().member1(std::declval<std::vector<char> &>()));

public:

    static constexpr bool has_member1 = 
        std::experimental::is_detected_convertible_v<long long,
                                                     has_member1_t,
                                                     USC>;
};

The problem is I also need to determine if class has certain template member function with following signature:

template<typename Derived>
int member2(Eigen::ArrayBase<Derived> &&)

I’ve tried to do it like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

//Inside Descriptor

template<class T, class U>
using has_member2_t = 
    decltype(std::declval<T>().member2(std::declval<Eigen::ArrayBase<U> &&>()));

static constexpr bool has_member2 = 
    std::experimental::is_detected_convertible_v<long long,
                                                 has_member2_t,
                                                 USC>;

but it doesn’t work. As I’m not really experienced with C++ TMP I would like to know is there a way to achieve this with std::experimental::is_detected or some other utility?

>Solution :

If c++20 is an option, this kind of code has been made a lot easier to both read and write by using concepts.

#include <iostream>
#include <vector>

struct Foo {
    int member1(int) {
        return 1;
    }

    template <typename T>
    double member2(std::vector<T>) {
        return 2.5;
    }
};

struct Bar {};

template <typename T>
concept MyConcept = requires (T t) {
    { t.member1(0) } -> std::same_as<int>;              // We can check return type
    { t.template member2<int>(std::vector<int>{}) };    // but we don't have to
};

int main() {
    static_assert(MyConcept<Foo>);
    static_assert(!MyConcept<Bar>);
}

The issue with your attempt is that you are not passing anything as U for the check. I would also modify it to use the .template member2<...> syntax to explicitly check for a template.

Here is an example of that.

#include <iostream>
#include <vector>
#include <utility>
#include <experimental/type_traits>

struct Foo {
    int member1(int) {
        return 1;
    }

    template <typename T>
    double member2(std::vector<T>) {
        return 2.5;
    }
};

struct Bar {};

template<class T, class U>
using has_member2_t = 
    decltype(std::declval<T>().template member2<U>(std::declval<std::vector<U> &&>()));

int main() {
    static constexpr bool has_member2_Foo = 
    std::experimental::is_detected_convertible_v<long long,
                                                 has_member2_t,
                                                 Foo, double>;

    static constexpr bool has_member2_Bar = 
    std::experimental::is_detected_convertible_v<long long,
                                                 has_member2_t,
                                                 Bar, double>;

    static_assert(has_member2_Foo);
    static_assert(!has_member2_Bar);
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading