tags:

views:

76

answers:

1

Hello all,

It's my first question there, and it's a noobish question :).

I'm facing to a problem with C++ and Qt 4.6, because I want to factorize some of my code which is invoking some public slots of a QObject, through the QMetaMethod::invoke() method.

The problem I'm facing to, is that the Q_ARG macro is defined as follow:

#define Q_ARG(type, data) QArgument<type >(#type, data)

That says that I should know at compile time the type. But I get on the other hand my arguments for the method, which are coming as QVariants. I can get their types through the ->type() accessor, which returns an enum value of type QVariant::Type, but naturally not as compile time type.

So to simply generates the arguments for the invocation, I made the following macro:

#define PASS_SUPPORTED_TYPE(parameterToFill, requiredType, param, supported) {      \
                                            \
        switch (requiredType) {                         \
            case QVariant::String:                      \
                parameterToFill = Q_ARG(QString,            \
                        param.value<QString>());        \
            break;                              \
                                            \
            case QVariant::Int:                         \
                parameterToFill = Q_ARG(int, param.value<int>());   \
            break;                              \
                                                        \
            case QVariant::Double:                      \
                parameterToFill = Q_ARG(double, param.value<double>()); \
            break;                              \
                                                        \
            case QVariant::Char:                        \
                parameterToFill = Q_ARG(char, param.value<char>());     \
            break;                              \
                                                        \
            case QVariant::Bool:                        \
                parameterToFill = Q_ARG(bool, param.value<bool>());     \
            break;                              \
                                                        \
            case QVariant::Url:                         \
                parameterToFill = Q_ARG(QUrl, param.value<QUrl>());     \
            break;                              \
                                                        \
            default:                            \
                supported = false;                  \
                                            \
        }                                   \
                                            \
        supported = true;                           \
}

The same could be done in a method which could return true or false instead of setting the "supported" flag, but this would force me to make heap allocation in this case, because the "param.value()" call returns a copy of the QVariant value, which I should store in heap through a new or through a memset.

And that is my problem, I don't want to do heap allocation in this method, because this will get called thousands of time (this is a request handling module).

for (int k = 0; k < methodParams.size(); ++k) {
    QVariant::Type paramType = QVariant::nameToType(methodParams[k].toAscii());

    [...]

    bool supportedType = false;

    PASS_SUPPORTED_TYPE(
            paramsToPass[k], 
            paramType, 
            params[k],
            supportedType);
   [...]
}

metaMethod.invoke(objectToCall, paramsToPass[0], paramsToPass[1], paramsToPass[2] [...]);

This does not please me because it's not type safe. So the question I'm asking myself is how could I fire out this macro, and replace it with a method which would do stack allocation and not heap allocation?

I thank you all in advance for your help and interest.

+4  A: 

And that is my problem, I don't want to do heap allocation in this method, because this will get called thousands of time (this is a request handling module).

Don't second guess performances issues. Yes, stack allocation is faster and yes, one should avoid copies when they aren't needed. However, this looks like premature optimization to me.

It seems you're building a very complex code architecture in order to save a few CPU cycles. In the end, you'll maybe don't be able to tell reliably what gets called and how many times. And you'll have an unmaintainable code.

My advice would be: focus on the correctness and simplicity of your code and if you really face performances issues at some point, profile your code to see what is wrong.

ereOn
Thank you, I'll do it with heap allocation, I can always come back later on it to optimize some parts.
+1 good advice. Premature optimization is a code smell.
Sam Miller