0

First off I would like to mention that this works with MSVC but not with clang. I am using Clang with c++11.

I have a function pointer:

typedef void (*Log) (const char* title, const char* msg, const char* file, int line);

I have this struct:

 struct FunctionList
    {
    protected:
        static const int kNbrMax = 32;
        FunctionList();
        bool Add(const void* f);
        bool Remove(const void* f);

        const void*     m_functions[kNbrMax];
    };

And this class:

template<typename T>
struct MessageFunctionList
    : public FunctionList
{
public:
    MessageFunctionList(T defaultFunction)  
    {
        Add(defaultFunction);
    }

    void Call(const char* title,const char* cause,const char* file,int line)
    {
        for (unsigned long i = 0;i < m_nbrUsed;++i)
        {
            reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
        }
    }
}

I am creating it like so:

static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{

}

MessageFunctionList<Log> functionList(DefaultLogMessageFunction)

But I get the compile time error:

reinterpret_cast from 'const void ' to 'void ()(const char *, const char *, const char *, int)' casts away qualifiers for line: reinterpret_cast(m_functions[i])(title,cause,file,line);

So as far as I understand I am trying to cast my const list of functions to a non const value. That is not allowed which makes sense. So I tried the following:

const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);

But that does not work either.

This works:

void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);

But I would like to avoid using a const cast. What am I doing wrong? How can I call this const function? Or is it simply not allowed because it does not know if the function being called is a const function or not? Or perhaps it is because my static function is not a member of a class so it can not be declared const?

4
  • Please provide a minimal reproducible example. I can't tell what you're actually doing. Commented Aug 3, 2016 at 16:00
  • What am I missing? What is included that is not necessary? I think I have included everything needed? Do you want a zipped project? I am trying to store a list of function pointers to log functions. Commented Aug 3, 2016 at 16:01
  • 1
    You're missing an MCVE. I'm looking for a short, self-contained, example that I can see what compile error you're getting and what you're trying to do. All I see are several unconnected code fragments and I do not understand either what you're trying to do or why it's failing. Commented Aug 3, 2016 at 16:08
  • godbolt.org/g/RfbrUI It seems to compile fine though which is a problem. I am not sure why my clang compiler is failing. Commented Aug 3, 2016 at 16:18

1 Answer 1

3

You are storing the function pointers as const void*:

const void*     m_functions[kNbrMax];

And you are trying to cast them to T and call it using reinterpret_cast:

reinterpret_cast<T>(m_functions[i])(title,cause,file,line);

However, reinterpret_cast cannot remove const qualifier from a type, therefore, you should first remove the const using const_cast:

reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

However, please note that const_cast engenders undefined behavior and is unsafe. So is calling a function pointer returned from reinterpret_cast if the original pointer was not actually a T.

Edit: You can call a const qualified function pointer, however, then the reinterpret_cast should contain the const qualifier:

reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks, but I provided that same solution myself at the bottom of my post. I dont understand why I cant store and call a const function. I am trying to avoid const cast.
I tried that as well figuring it would work but I get the same error. Its weird because online clang compilers seem to compile it without error.
@marsh, so does online and offline g++ compilers: coliru.stacked-crooked.com/a/ccf66094fb802e7d
@marsh, I have no idea, however it looks like a compiler problem instead of a language one. Also, as far as I know, it is undefined to cast a function pointer to a void*. Why don't you use T directly to store the function pointers, by simply letting the base class go?
@marsh, the function pointer type can still change, check this one, it is type safe: coliru.stacked-crooked.com/a/6759067d687386a6
|

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.