how can i get error from __attribute__((weak))?

Pages: 12
i'm trying using __attribute__((weak)) on a prototype function:
1
2
3
4
5
6
7
8
9
10
//ClassWithEvents(test,FormEvents, b);
class InstanceName : public test<InstanceName>
{ // manual expansion of ClassWithEvents
public:
    InstanceName() : test(this){;}
    ~InstanceName(){;}
public:
    void MouseClick() __attribute__((weak));
    void Move() __attribute__((weak));
} InstanceName;

heres how i call it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename CBase>
class test
{
    CBase* atPointer = nullptr;
public:
    void MouseClick(){;};
    test(CBase *clsPointer) : atPointer(clsPointer)
    {
        
        try
        {
            clsPointer->MouseClick();
        }
        catch(std::exception& e)
        {
            MouseClick();
        }
    }
    void call()
    {
        atPointer->MouseClick();
    }
};

why the 'try' don't catch the __attribute__((weak)) error?
i get a window: "the program stops responding"
https://imgur.com/a/0e9f8ZX
what you can tell me?
I'm not an expert in this, but are you trying to implement the Curiously Recurring Template Pattern (CRTP)?

I believe you are erroneously trying to use weak symbols in an attempt to cover up the actual problem: you never define an implementation for InstanceName::MouseClick(), but then try to call it within your test constructor. I don't quite understand what you're doing here.

A function that isn't implemented doesn't throw an exception, as far as I know, you simply are dereferencing a function that doesn't exist -- this is undefined behavior.

Also, in general avoid global objects, like your InstanceName object. Define it in main or another function instead.

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
36
37
38
39
40
41
42

#include <iostream>
#include <exception>

template <typename CBase>
class test
{
    CBase* atPointer = nullptr;
public:
    void MouseClick(){;};
    test(CBase *clsPointer) : atPointer(clsPointer)
    {
        try
        {
            std::cout << "About to call MouseClick()" << std::endl;
            clsPointer->MouseClick();
        }
        catch(std::exception& e)
        {
            MouseClick();
        }
    }
};

class InstanceName : public test<InstanceName>
{
public:
    InstanceName() : test(this){;}
    ~InstanceName(){;}
public:
    void MouseClick() __attribute__((weak));
};

void InstanceName::MouseClick()
{
    std::cout << "Derived behavior" << std::endl;
}

int main()
{
    InstanceName in;
}


Note: using __attribute__((weak)) is now unnecessary here, and your try-catch block is also not necessary.
Last edited on
Weak symbols allow declaring a symbol which can be overridden later. If you invoke a function with no definition at all, your program will crash.

Assuming you're compiling to ELF, the address of a weakly declared function is also zero, so you could do this:

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
36
37
38
39
40
41
42
43
44
45
46
#include <iostream>

struct Clickable {
  virtual ~Clickable() = default;
  virtual void call() = 0;
};

#if defined __GNUC__
#define WEAK_SYMBOL [[gnu::weak]]
#elif defined __clang__
#define WEAK_SYMBOL [[llvm::weak]]
#endif

#define SYMBOL_DEFINED(sym) (static_cast<bool>(sym))

template <typename Derived> struct Test : Clickable {
  Test(Derived *derived) : d{derived} {}

  void call() override {
    if (SYMBOL_DEFINED(&Derived::mouse_click))
      d->mouse_click();
    else {
      std::cout << "no definition\n";
      // throw std::bad_function_call{};
    }
  }

private:
  Derived *d = nullptr;
};

struct Button : Test<Button> {
  Button() : Test{this} {}
  WEAK_SYMBOL void mouse_click();
};

// Optionally define+link this function later.  Try commenting it out:
void Button::mouse_click() { std::cout << "button clicked\n"; }


int main() {
  Button x;
  Clickable &b = x;

  b.call();
}

don't resolve my problem.
i need avoid the error, if the InstanceName::MouseClick() isn't defined.
If you don't comment out line 38 in mbozzi's code, the output will be "button clicked"
If you do comment out line 38, Derived::mouse_click will be a null function pointer, and the output should be "no definition", with no runtime errors happening. Are you experiencing different behavior?

mbozzi's code works on MinGW (Windows) for me, as well.

Edit: I realize you posted at almost the same time as mbozzi, so you might not have seen his post.
Last edited on
almost done... great.
that macros are only for 1 function?
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#if defined __GNUC__
#define WEAK_SYMBOL [[gnu::weak]]
#elif defined __clang__
#define WEAK_SYMBOL [[llvm::weak]]
#endif

#define SYMBOL_DEFINED(sym) (static_cast<bool>(sym))


template <typename CBase>
class test
{
    CBase* atPointer = nullptr;
public:
    void MouseClick(){;};
    void Move(){;};
    test(CBase *clsPointer) : atPointer(clsPointer)
    {
        if (SYMBOL_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();
        else
            MouseClick();

        if (SYMBOL_DEFINED(&CBase::Move))
            atPointer->Move();
        else
            Move();
    }
    void call()
    {
        if (SYMBOL_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();
        else
            MouseClick();

        if (SYMBOL_DEFINED(&CBase::Move))
            atPointer->Move();
        else
            Move();
    }
};

class InstanceName : public test <InstanceName>
{ // manual expansion of ClassWithEvents
public:
    InstanceName(): test(this){;}
    ~InstanceName(){;}
public:
    WEAK_SYMBOL  void MouseClick();
    WEAK_SYMBOL void Move();
} InstanceName;

void InstanceName::MouseClick()
{
    std::cout << "Mouse click";
}


void InstanceName::Move()
{
   std::cout << "Move";
}


int main()
{
    InstanceName.call();
    std::cin.get();
    return 0;
}

i'm getting 2 times the MouseClick() and not 1 the Move().. why?
(i'm using 2 functions, but i can have much more.)
i'm getting 2 times the MouseClick() and not 1 the Move().. why?

Sorry, can you re-phrase that? I'm not sure what you mean.
My output for your program (once I add #include <iostream> and using namespace std;) is
Mouse clickMoveMouse clickMove

As in,
"Mouse click", "Move", "Mouse click", "Move".

Are you getting different output?
i'm getting:
"Mouse click", "Mouse click", "Mouse click", "Mouse click".
I'm not sure then, maybe mbozzi knows. Would you mind posting your full source code file that gives you that particular output? Your above post isn't actually your full code.

Also, if you're working in an IDE or something, try cleaning your project (maybe something leftover from a previous build).
Last edited on
heres the entire code:
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>

#if defined __GNUC__
#define WEAK_SYMBOL [[gnu::weak]]
#elif defined __clang__
#define WEAK_SYMBOL [[llvm::weak]]
#endif

#define SYMBOL_DEFINED(sym) (static_cast<bool>(sym))

template <typename CBase>
class test
{
    CBase* atPointer = nullptr;
public:
    void MouseClick(){;};
    void Move(){;};
    test(CBase *clsPointer) : atPointer(clsPointer)
    {
        if (SYMBOL_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();
        else
            MouseClick();

        if (SYMBOL_DEFINED(&CBase::Move))
            atPointer->Move();
        else
            Move();
    }
    void call()
    {
        if (SYMBOL_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();
        else
            MouseClick();

        if (SYMBOL_DEFINED(&CBase::Move))
            atPointer->Move();
        else
            Move();
    }
};

class InstanceName : public test <InstanceName>
{
public:
    InstanceName(): test(this){;}
    ~InstanceName(){;}
public:
    WEAK_SYMBOL void MouseClick();
    WEAK_SYMBOL void Move();
} InstanceName;

void InstanceName::MouseClick()
{
    std::cout << "Mouse click";
}


void InstanceName::Move()
{
   std::cout << "Move";
}


int main()
{
    InstanceName.call();
    std::cin.get();
    return 0;
}

on compiler i only use C++11 and the 2 static libgcc and libstdc++
Last edited on
i'm getting:
"Mouse click", "Mouse click", "Mouse click", "Mouse click".


I get the same output as @Ganado.

If you are indeed using GCC or Clang, please post the output of the command
g++ --version -v
or
clang++ --version -v
And whatever command(s) you're using to compile and link the above.
- i'm using Code blocks 17.12(from 25 December 2017.. maybe it's updated, but i must see) with Mingw 5.1.0 (came with code blocks installer.. maybe it's a big problem... the Mingw can't be updated(i accept more info about the Code Blocks came with Mingw);
- but i have installed the Mingw 7.2.0;
- yes i know change the Compiler folder and files.
- and yes.. thank you.. i have the 'Clean' command on Build menu.
and now works just fine...
(i did with new names, on macros)
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>

#if defined __GNUC__
#define EVENT [[gnu::weak]]
#elif defined __clang__
#define EVENT [[llvm::weak]]
#endif

#define IS_EVENT_DEFINED(sym) (static_cast<bool>(sym))

template <typename CBase>
class test
{
    CBase* atPointer = nullptr;
public:
    test(CBase *clsPointer) : atPointer(clsPointer)
    {
        if (IS_EVENT_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();


        if (IS_EVENT_DEFINED(&CBase::Move))
            atPointer->Move();

    }
    void call()
    {
        if (IS_EVENT_DEFINED(&CBase::MouseClick))
            atPointer->MouseClick();

        if (IS_EVENT_DEFINED(&CBase::Move))
            atPointer->Move();

    }
};

class InstanceName : public test <InstanceName>
{ 
public:
    InstanceName(): test(this){;}
    ~InstanceName(){;}
public:
    EVENT void MouseClick();
    EVENT void Move();
} InstanceName;

void InstanceName::MouseClick()
{
    std::cout << "Mouse click\n";
}


void InstanceName::Move()
{
   std::cout << "Move\n";
}


int main()
{
    InstanceName.call();
    std::cin.get();
    return 0;
}

i'm sorry asking: but i must use uppercase with macros names?
(ok... i can use any name... but is good asking)
Last edited on
do you know the '#elif' for Visual Studio?
i'm sorry, but do you know another '#elif' for Visual Studio?
1
2
3
4
5
#if defined __GNUC__
#define EVENT [[gnu::weak]]
#elif defined __clang__
#define EVENT [[llvm::weak]]
#endif 

yes these macro isn't compatible with Visual Studio
maybe... but i'm asking: what is the 'defined' for i use with Visual Studio?
#if defined and #elif defined seem to work just fine in VS 2015.
Last edited on
helios: thank you
1
2
3
4
5
6
7
#if defined __GNUC__
#define EVENT [[gnu::weak]]
#elif defined __clang__
#define EVENT [[llvm::weak]]
#elif define  _MSC_VER
#define EVENT [[msvc::weak]]
#endif 

but the '#define' is correct too?
that link don't show the '#define'
Pages: 12