Tirafesi
Tirafesi

Reputation: 1479

How to pass string to macro function

I'm using this lib to embed some resource files into an executable.

The resources can be accessed by the macro function LOAD_RESOURCE.

The resources I want to embed:

Loading the common resources is easy:

 Resource res1 = LOAD_RESOURCE(resource_my_resource1_xml);
 Resource res2 = LOAD_RESOURCE(resource_my_resource2_xml);

My problem is that I only know the type at runtime, so how can I load resources 3 and 4?

My current solution is through a switch case:

Resource res3, res4;
switch (type)
{
    default:
    case 1:
        res3 = LOAD_RESOURCE(resource_type1_my_resource3_xml);
        res4 = LOAD_RESOURCE(resource_type1_my_resource4_xml);
        break;
    case 2:
        res3 = LOAD_RESOURCE(resource_type2_my_resource3_xml);
        res4 = LOAD_RESOURCE(resource_type2_my_resource4_xml);
        break;
}

However, this isn't very efficient nor pretty when I have N types and N resources for each.

Is there a better alternative? Can I somehow pass a string to the macro function as the argument? Something like LOAD_RESOURCE("resource_type" + type + "_my_resourceN_xml")?

Upvotes: 0

Views: 414

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 123431

Can I somehow pass a string to the macro function as the argument?

No you cannot. Macros are expanded by the preprocessor before the compiler actually gets to see the code. In a nutshell, macros are about textual replacment not more.

My problem is that I only know the type at runtime, so how can I load resources 3 and 4?

I don't know the library, but the Resource is merely a pointer to data and a data length. "Loading" a resource does not more than providing you a handle to it. Hence I would load all resoures on program start and then access them at runtime as needed.

For the sake of the example, lets say this is the library code

#define LOAD_RESOURCE(path) ([](){ return Resource{}; })()
struct Resource {};

Then I would perhaps use this:

#include <map>
#include <utility>

using key = std::pair<int,int>;
std::map<key,Resource> load_all_resources(){
    return { 
        { {1,1} , LOAD_RESOURCE(resource_type1_my_resource1_xml) },
        { {1,2} , LOAD_RESOURCE(resource_type1_my_resource2_xml) }
    };
}
int main (){
    auto resources = load_all_resources();
    auto type = 1;
    auto res1 = resources[{type,1}];
}

To make the loading more copy-paste friendly one can use a macro

#define MY_LOAD_RESOURCE(type,N) { {type,N}, LOAD_RESOURCE( resource_type##type##_my_resource##N_xml )}

such that

std::map<key,Resource> load_all_resources(){
    return { 
        MY_LOAD_RESOURCE(1,1),
        MY_LOAD_RESOURCE(1,2),
    };
}

expands to the same as above. Complete example.

Upvotes: 1

Related Questions