Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ copy_if lambda capturing std::string

Tags:

c++

c++11

lambda

This is a follow up question from here: C++ - Developing own version of std::count_if?

I have the following function:

// vector for storing the file names that contains sound 
std::vector<std::string> FilesContainingSound; 

void ContainsSound(const std::unique_ptr<Signal>& s)
{
    // Open the Wav file 
    Wav waveFile = Wav("Samples/" + s->filename_); 

    // Copy the signal that contains the sufficient energy 

    std::copy_if(waveFile.Signal().begin(), waveFile.Signal().end(), 
                 FilesContainingSound.begin(), [] (const Signal& s) {

                     // If the energy bin > threshold then store the 
                     // file name inside FilesContaining
                 }
}

But to me, I only need to capture the string "filename" inside of the lambda expression, because I'll only be working with this. I just need access to the waveFile.Signal() in order to do the analysis.

Anyone have any suggestions?

EDIT:

std::vector<std::string> FilesContainingSound;
std::copy_if(w.Signal().begin(), w.Signal().end(), 
             FilesContainingSound.begin(), [&] (const std::unique_ptr<Signal>& file) {

                 // If the energy bin > threshold then store the 
                 // file name inside FilesContaining
             });
like image 205
Phorce Avatar asked Oct 02 '22 04:10

Phorce


1 Answers

You seem to be getting different levels of abstraction confused here. If you're going to work with file names, then you basically want something on this order:

std::vector<std::string> input_files;
std::vector<std::string> files_that_contain_sound;

bool file_contains_sound(std::string const &filename) { 
     Wav waveFile = Wav("Samples/" + filename);

     return binned_energy_greater(waveFile, threshold);
}

std::copy_if(input_files.begin(), input_files.end(),
             std::back_inserter(files_that_contain_sound),
             file_contains_sound);

For the moment I've put the file_contains_sound in a separate function simply to make its type clear -- since you're dealing with file names, it must take a file name as a string, and return a bool indicating whether that file name is one of the group you want in your result set.

In reality, you almost never really want to implement that as an actual function though--you usually want it to be an object of some class that overloads operator() (and a lambda is an easy way to generate a class like that). The type involved must remain the same though: it still needs to take a file name (string) as a parameter, and return a bool to indicate whether that file name is one you want in your result set. Everything dealing with what's inside the file will happen inside of that function (or something it calls).

like image 51
Jerry Coffin Avatar answered Oct 13 '22 10:10

Jerry Coffin