Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting std::vector container into an std::set using std::transform

Tags:

c++

c++11

More specifically I have a vector of some struct

std::vector<SomeStruct> extensions = getThoseExtensions();

where someStructVariable.extensionName returns a string.

And I want to create a set of extensionName, something like this std::set<const char*>.

Process is fairly straightforward when done using some for loops but I want to use std::transform from <algorithm> instead.


std::transform has four parameters.

1,2. First range (to transform first range from and to)

3. Second range/inserter (to transform second range)

4. A function


This is what I have so far

auto lambdaFn = 
    [](SomeStruct x) -> const char* { return x.extensionName; };

 std::transform(availableExtensions.begin(),
                availableExtensions.end(),
                std::inserter(xs, xs.begin()),
                lambdaFn);

because there's no "proper context" for std::back_inserter in std::set I'm using std::inserter(xs, xs.begin()).


The problem is I'm trying to return stack mem in my lambda function. So how do I get around this problem?

Oddly enough if I remove return from the function it works just like I expect it to! But I don't understand why and that strikes fear of future repercussion.


EDIT:

I'm using several structs in place of SomeStruct like VkExtensionProperties defined in vulkan_core

typedef struct VkExtensionProperties {
    char        extensionName[VK_MAX_EXTENSION_NAME_SIZE];
    uint32_t    specVersion;
} VkExtensionProperties;

From Khronos specs

like image 974
atis Avatar asked Oct 15 '25 15:10

atis


1 Answers

You probably can't create a set of char * unless all instances of extensionName with the same value point to the same char array (it would store unique pointers instead of unique values). If you use std::set<std::string> instead this will both work and only store unique values and solve your variable lifetime problem as std::string takes care of copying (or moving) itself for you where necessary:

auto lambdaFn = 
    [](const SomeStruct& x) { return std::string(x.extensionName); };
std::set<std::string> xs;
std::transform(availableExtensions.begin(),
                availableExtensions.end(),
                std::inserter(xs, xs.begin()),
                lambdaFn);
like image 105
Alan Birtles Avatar answered Oct 18 '25 05:10

Alan Birtles



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!