0
votes

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?

1
Please provide a minimal reproducible example. I can't tell what you're actually doing. - Barry
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. - marsh
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. - Barry
godbolt.org/g/RfbrUI It seems to compile fine though which is a problem. I am not sure why my clang compiler is failing. - marsh

1 Answers

3
votes

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);