Last active
November 15, 2024 03:47
-
-
Save maddouri/0da889b331d910f35e05ba3b7b9d869b to your computer and use it in GitHub Desktop.
Checking the Existence of a C++ Class Member at Compile Time
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// A compile-time method for checking the existence of a class member | |
// @see https://general-purpose.io/2017/03/10/checking-the-existence-of-a-cpp-class-member-at-compile-time/ | |
// This code uses "decltype" which, according to http://en.cppreference.com/w/cpp/compiler_support | |
// should be supported by Clang 2.9+, GCC 4.3+ and MSVC 2010+ (if you have an older compiler, please upgrade :) | |
// As of "constexpr", if not supported by your compiler, you could try "const" | |
// or use the value as an inner enum value e.g. enum { value = ... } | |
// check "test_has_member.cpp" for a usage example | |
/// Defines a "has_member_member_name" class template | |
/// | |
/// This template can be used to check if its "T" argument | |
/// has a data or function member called "member_name" | |
#define define_has_member(member_name) \ | |
template <typename T> \ | |
class has_member_##member_name \ | |
{ \ | |
typedef char yes_type; \ | |
typedef long no_type; \ | |
template <typename U> static yes_type test(decltype(&U::member_name)); \ | |
template <typename U> static no_type test(...); \ | |
public: \ | |
static constexpr bool value = sizeof(test<T>(0)) == sizeof(yes_type); \ | |
} | |
/// Shorthand for testing if "class_" has a member called "member_name" | |
/// | |
/// @note "define_has_member(member_name)" must be used | |
/// before calling "has_member(class_, member_name)" | |
#define has_member(class_, member_name) has_member_##member_name<class_>::value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// usage example: check for the existence of a "sayHi" member ////////////////////////////////////// | |
// clang++ -std=c++11 -pedantic -Wall -Wextra test_has_member.cpp -o test_has_member && ./test_has_member | |
// g++ -std=c++11 -pedantic -Wall -Wextra test_has_member.cpp -o test_has_member && ./test_has_member | |
#include <iostream> // cout, endl | |
#include <iomanip> // std::boolalpha | |
#include "has_member.hpp" | |
struct A // has a "sayHi" member | |
{ | |
void sayHi() { std::cout << "Hi there!" << std::endl; } | |
}; | |
struct B // doesn't have a "sayHi" member | |
{ | |
void sayBye() { std::cout << "Bye bye!" << std::endl; } | |
}; | |
// define a "sayHi" "member checker" class | |
define_has_member(sayHi); | |
int main() | |
{ | |
using std::cout; | |
using std::endl; | |
cout << std::boolalpha; // display "true" or "false" for booleans | |
A a; | |
B b; | |
// check the existence of "sayHi" | |
cout << "has_member(A, sayHi) " << has_member(A, sayHi) << endl; | |
cout << "has_member(B, sayHi) " << has_member(B, sayHi) << endl; | |
cout << endl; | |
// same thing, using decltype on instances | |
cout << "has_member(decltype(a), sayHi) " << has_member(decltype(a), sayHi) << endl; | |
cout << "has_member(decltype(b), sayHi) " << has_member(decltype(b), sayHi) << endl; | |
return 0; | |
} |
Is it possible to check if A has a function sayHi(int)? basically check signature also.
Is it possible to check if A has a function sayHi(int)? basically check signature also.
I'm assuming you mean a way to disambiguate sayHi(float)
from sayHi(int)
or sayHi(string)
I believe this will only work if the signature is hinted at via a template (i.e. a function template on the member sayHi<T>(T)
) because C++ gives no way to specify the overload except at the call site and the way yes_type
is defined here is not going to do that. Perhaps there is a more convoluted way of defining yes_type
to use std::declval
so that the disambiguation can happen. At a first glance, it is not obvious.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a way to verify existence of private members too in c++?