1

I'm having an issue calling a member function pointer that is atomic:

class test
{
   typedef void(test::*ProcessPtr)();
   std::atomic<ProcessPtr> _processPtr;  
   void process() {}
}

int main(int argc, char** argv)
{
    test t;
    t._processPtr = &test::process;
    (t.*_processPtr)();  
}

The error is:

t.cpp:238:6: error: ‘_processPtr’ was not declared in this scope (t.*_processPtr)();

Not quite sure what the issue is.. Can you not deference an "atomic" member function pointer?

8
  • Try (t.*t._processPtr)(); Commented Jul 13, 2018 at 19:16
  • Now I get: error: ‘t.test::_processPtr’ cannot be used as a member pointer, since it is of type ‘std::atomic<void (test::*)()>’ (t.*t._processPtr)(); Commented Jul 13, 2018 at 19:19
  • There's the answer to your question. :-) Commented Jul 13, 2018 at 19:21
  • 1
    Something like test::ProcessPtr pp = t._processPtr.load(); and (t.*pp)();? Commented Jul 13, 2018 at 19:47
  • It compiles but doesn't link for me with gcc4.8.3: t.cpp:(.text.startup+0x63): undefined reference to __atomic_store_16' t.cpp:(.text.startup+0x70): undefined reference to __atomic_load_16' Commented Jul 13, 2018 at 20:42

3 Answers 3

2

As super pointed out you need to use the object twice:

(t.*t._processPtr.load())();
 ^  ^             ^----- load() because it's an atomic variable
 |  |---- this loads the function pointer stored inside of t
 |------- actual Object to call the member function pointer on

So you end up with this:

int main(int argc, char** argv)
{
    test t;
    t._processPtr = &test::process;
    (t.*t._processPtr.load())();  
}
Sign up to request clarification or add additional context in comments.

Comments

0

_processPtr is not availiable. make it public like so.

class test
{
public:
    typedef void(test::*ProcessPtr)();
    std::atomic<ProcessPtr> _processPtr;
    void process() {};
}

with atomic you use .store() and .load() to write and read. not sure how it works with pointers though.

1 Comment

it was public.. just forgot to type that out
0

I found out why. this relates to the template argument deduction.

If you see the template class 'atomic', have a class of primary T and class specialize with T *. then I compare the pointer to function and pointer to function member. code can be seen below:

#include <iostream>

template<typename T>
struct A
{ 
    static void Call(){std::cout << "Call T" << std::endl;}
};
template<typename T>
struct A<T*>
{ 
    static void Call(){std::cout << "Call T*" << std::endl;}
};

struct B {};

int main()
{
    A<void(B::*)()>::Call();
    A<void(*)()>::Call();
}

output:

Call T
Call T*

Suggest improvement, use a double pointer to function member:

update in class test, from std::atomic<ProcessPtr> _processPtr; to std::atomic<ProcessPtr*> _processPtr;

and update in main function:

int main()
{
    test t;
    test::ProcessPtr d = &test::process;
    t._processPtr = &d;
    (t.*(*(t._processPtr)))();  
}

1 Comment

yes that would work, though another level of indirection

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.