macro directive: how test if the function is defined?

if the function isn't defined, the compiler give me an error.
so what is the directive for i control it?
i'm trying:
1
2
3
4
5
#if !defined(clsPointer->MouseClick)
            clsPointer->MouseClick();
        #else
            MouseClick();
        #endif 

but i get errors:
"missing ')' after "defined""
so what i'm doing wrong?
You can't. Processor directives (lines starting with #) are handled before the code is compiled so it doesn't understand C++ code at all.
Last edited on
and test if theres an error?
that 'if' directive is for call 1st or the 2nd, depending if the compiler give me an error
these '#ifdef' isn't correct.. why?
1
2
3
4
5
#ifdef  clsPointer->MouseClick //if is defined
            clsPointer->MouseClick();
        #else
            MouseClick();
        #endif // clsPointer 

did i miss something on macro directive?
Last edited on
these '#ifdef' isn't correct.. why?

Because #ifdef (and defined) only works for macros that has been defined using #define. I think you might be able to accomplish what you want using templates (SFINAE) but I don't know how.
Last edited on
i thot the lambda helped me.. but no success :(
1
2
3
4
5
6
7
test(ClassDerived *clsPointer)
    {
        std::function<void()> func =clsPointer->MouseClick;
        if(func)
            clsPointer->MouseClick();
        else
            MouseClick();

error:
" conversion from '<unresolved overloaded function type>' to non-scalar type 'std::function<void()>' requested"
Separating "meta-levels" is the trickiest part of metaprogramming, IMO. It can be difficult to remember what code runs when. The preprocessor operates on text, before the compiler touches your code, before anything (save preprocessor macros) are defined.

I think you might be able to accomplish what you want using templates (SFINAE)

Yes - for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <type_traits>

# include <iostream>
struct A {
    void MouseClick() const { std::cout << "non-default mouse-click\n"; } 
};

struct B {}; 

void MouseClick() { std::cout << "default mouse-click\n"; }


template <typename T, typename = decltype(std::declval<T>().MouseClick())> 
constexpr std::true_type has_mouse_click_impl(int) { return {}; }
template <typename T>
constexpr std::false_type has_mouse_click_impl(...) { return {}; }

template <typename T>
constexpr auto has_mouse_click() { return has_mouse_click_impl<T>(0); }

template <typename T, typename = std::enable_if_t<has_mouse_click<T>()>>
decltype(auto) click_impl(T&&x, int) { return std::forward<T>(x).MouseClick(); } 
template <typename T>
decltype(auto) click_impl(T&& x, ...) { return MouseClick(); }

template <typename T>
decltype(auto) click(T&& x) { return click_impl(std::forward<T>(x), 0); }

int main() {
    A a;
    click(a);
    B b;
    click(b);

}


Or, if the test must be generated in-line (because the name you're testing for is only known at the call-site), use something like this:
http://www.cplusplus.com/forum/general/234709/#msg1053368

Edit: fixed typo, added complete example
http://coliru.stacked-crooked.com/a/67b5bc4bec519038

Note: it's much better to avoid hacks like that by keeping the interface uniform. Must X::MouseClick be a member function?
Last edited on
these is for my global functions macro. it must have them, but don't means that i must define them all.
your sample: too much code for i control it :(
i must learn more about them
i'm sorry that all templates, can be an entire class?
and maybe we don't need 'click'(another name).
just a thot
With the risk of stating the obvious, I just want to make it clear that the decision on which function to call is handled at compile time, so you cannot use the method shown by mbozzi to make runtime decisions based on the object's dynamic type when using pointers or references.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ....

struct Base
{
};

struct Derived : Base {
    void MouseClick() const;
};

int main()
{
	Derived obj;
	click(obj); // This will call Derived::MouseClick().

	Base& ref = obj;
	click(ref); // This will call the global ::MouseClick() function.
}
Last edited on
Virtually select a different function for each derived class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <typeinfo>

template <typename T> void click_impl(T const &) {
  std::cout << "default click: " << typeid(T).name() << '\n';
}
class Derived1;

void click_impl(Derived1 const &) {
  std::cout << "non-default click: Derived1\n";
}

struct Base {
  void click() { dispatch_click(); }

private:
  virtual void dispatch_click() = 0;
};

class Derived1 : public Base {
  virtual void dispatch_click() override { click_impl(*this); }
};

class Derived2 : public Base {
  virtual void dispatch_click() override { click_impl(*this); }
};

int main() {
  Derived1 d1;
  Derived2 d2;

  Base &rd1 = d1, &rd2 = d2;
  rd1.click();
  rd2.click();
}


Last edited on
Topic archived. No new replies allowed.