# Detecting existence of a class member

I wanted to detect if I have a member in a simple POD struct and after some searching and merging some methods I found on the web I've come up with this solution:

#include <iostream>

template<class...Fs>
struct funcs_t{};

template<class F0, class...Fs>
struct funcs_t<F0, Fs...>: F0, funcs_t<Fs...> {
funcs_t(F0 f0, Fs... fs):
F0(std::move(f0)), funcs_t<Fs...>(std::move(fs)...)
{}
using F0::operator();
using funcs_t<Fs...>::operator();
};

template<class F>
struct funcs_t<F>:F {
funcs_t(F f) : F(std::move(f)) {};
using F::operator();
};

template<class...Fs>
funcs_t<std::decay_t<Fs>...> funcs(Fs&&...fs) {
return {std::forward<Fs>(fs)...};
}

#define HAS_MEMBER(cls, memb)\
[](){\
auto with_memb = [](auto &&A, int x)\
-> decltype(typename std::remove_reference<decltype(A)>::type().memb, std::true_type())\
{\
return std::true_type();\
};\
auto with_no_memb = [](auto &&A, float x) -> std::false_type {\
return std::false_type();\
};\
auto has_memb = funcs(with_memb, with_no_memb);\
return has_memb(cls(), 1);\
}()

struct A {
int a;
int b;
};

int main(int argc, char const *argv[])
{
std::cout << HAS_MEMBER(A, b) << std::endl;
return 0;
}

• Why do you need this? What are you trying to achieve? – Martin York Jul 19 at 16:39
• I have different pod structs with many common fields with the same meaning and I wanted to print them on screen. I will see if I can use it for other things but for now that's what I needed it for. – Pangi Jul 19 at 18:45
• Please do not update the code in your question to incorporate feedback from answers, doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers. If you want a fixed-version of your code to be available, post it as answer linking to Deduplicator's for credit (or post it as a new question, but it's hardly a major change). – Mast Jul 19 at 19:04
• Ok, I'll keep that in mind. – Pangi Jul 19 at 19:16

1. Your detector fails in the face of overloading and templating. Also, it will only detect (static) member-variables and (static) member-functions. While you can extend it to types (and type-aliases), accepting templates and overloading would need better language-provided reflection-facilities.

Anyway, pure existence is generally uninteresting, supported operations count.

2. funcs() and funcs_t are nearly a generally useful abstraction.

Just use perfect forwarding instead of by-value and std::move(). Allowing for all callables, including final classes, function-pointers, member-function-pointers, and the same wrapped in a std::reference_wrapper would admittedly add significant amounts of code.

A good name would be overloaded.

3. HAS_MEMBER needlessly depends on default-constructing the passed class. Fix that by using decltype, std::declval() and unevaluated contexts.

4. If you don't use an argument, don't name it. Specifically for main(), just don't ask for it.

5. Don't use std::endl. In the rare cases you actually need to flush manually, be explicit and use std::flush. Nearly always you are just crippling performance.

6. return 0; is implicit for main(). Make of that what you will.