0

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:

  • resource/my_resource1.xml
  • resource/my_resource2.xml
  • resource/type1/my_resource3.xml
  • resource/type1/my_resource4.xml
  • resource/type2/my_resource3.xml
  • resource/type2/my_resource4.xml
  • ...

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")?

1
  • The preprocessor runs before any code is evaluated. Commented Dec 6, 2019 at 22:39

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

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.