How to conditionally define a lambda? Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Are functors actually faster than pointers to functions?How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?How to convert a std::string to const char* or char*?How can I profile C++ code running on Linux?Why are #ifndef and #define used in C++ header files?Undefined, unspecified and implementation-defined behaviorC++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?What is a lambda expression in C++11?What is an undefined reference/unresolved external symbol error and how do I fix it?Average values of a MAT channel

Multi tool use
Multi tool use

Recursive calls to a function - why is the address of the parameter passed to it lowering with each call?

Does using the Inspiration rules for character defects encourage My Guy Syndrome?

Married in secret, can marital status in passport be changed at a later date?

Unix AIX passing variable and arguments to expect and spawn

Why isn't everyone flabbergasted about Bran's "gift"?

How to ask rejected full-time candidates to apply to teach individual courses?

Is "ein Herz wie das meine" an antiquated or colloquial use of the possesive pronoun?

Is the Mordenkainen's Sword spell underpowered?

What's the difference between using dependency injection with a container and using a service locator?

Kepler's 3rd law: ratios don't fit data

How can I introduce the names of fantasy creatures to the reader?

lm and glm function in R

What documents does someone with a long-term visa need to travel to another Schengen country?

Why does BitLocker not use RSA?

Suing a Police Officer Instead of the Police Department

How to produce a PS1 prompt in bash or ksh93 similar to tcsh

Why does my GNOME settings mention "Moto C Plus"?

Assertions In A Mock Callout Test

Who can become a wight?

Does traveling In The United States require a passport or can I use my green card if not a US citizen?

How to get a single big right brace?

What is the ongoing value of the Kanban board to the developers as opposed to management

Why do C and C++ allow the expression (int) + 4*5?

How to mute a string and play another at the same time



How to conditionally define a lambda?



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!Are functors actually faster than pointers to functions?How do you set, clear, and toggle a single bit?How do I iterate over the words of a string?How to convert a std::string to const char* or char*?How can I profile C++ code running on Linux?Why are #ifndef and #define used in C++ header files?Undefined, unspecified and implementation-defined behaviorC++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?What is a lambda expression in C++11?What is an undefined reference/unresolved external symbol error and how do I fix it?Average values of a MAT channel



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








10















The following function will randomly "sprinkle salt" on a loaded image. For the sake of boosting performance, the conditional statement



uint j = rows == 1 ? 0 : randomRow(generator);


should not be inside the loop.



Instead, I want to define a lambda getJ before the loop as



auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


However, my code with this lambda does not compile with the following red squiggled text:



enter image description here



Question



How to conditionally define such a lambda?



void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);
uniform_int_distribution<uint> randomCol(0, cols - 1);



// auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


uchar * const data = mat.data;

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = rows == 1 ? 0 : randomRow(generator);
//uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;











share|improve this question



















  • 3





    "my code with this lambda does not compile" - What is the error you get?

    – Suma
    Apr 16 at 12:35











  • You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

    – VTT
    Apr 16 at 12:36







  • 5





    Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

    – Artyer
    Apr 16 at 12:40






  • 2





    Is a conditional really a performance issue here? Have you profiled the code?

    – Jesper Juhl
    Apr 16 at 12:42






  • 1





    @Artyer Done well, the call to the lambda can be inlined.

    – Angew
    Apr 16 at 12:43

















10















The following function will randomly "sprinkle salt" on a loaded image. For the sake of boosting performance, the conditional statement



uint j = rows == 1 ? 0 : randomRow(generator);


should not be inside the loop.



Instead, I want to define a lambda getJ before the loop as



auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


However, my code with this lambda does not compile with the following red squiggled text:



enter image description here



Question



How to conditionally define such a lambda?



void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);
uniform_int_distribution<uint> randomCol(0, cols - 1);



// auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


uchar * const data = mat.data;

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = rows == 1 ? 0 : randomRow(generator);
//uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;











share|improve this question



















  • 3





    "my code with this lambda does not compile" - What is the error you get?

    – Suma
    Apr 16 at 12:35











  • You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

    – VTT
    Apr 16 at 12:36







  • 5





    Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

    – Artyer
    Apr 16 at 12:40






  • 2





    Is a conditional really a performance issue here? Have you profiled the code?

    – Jesper Juhl
    Apr 16 at 12:42






  • 1





    @Artyer Done well, the call to the lambda can be inlined.

    – Angew
    Apr 16 at 12:43













10












10








10


1






The following function will randomly "sprinkle salt" on a loaded image. For the sake of boosting performance, the conditional statement



uint j = rows == 1 ? 0 : randomRow(generator);


should not be inside the loop.



Instead, I want to define a lambda getJ before the loop as



auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


However, my code with this lambda does not compile with the following red squiggled text:



enter image description here



Question



How to conditionally define such a lambda?



void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);
uniform_int_distribution<uint> randomCol(0, cols - 1);



// auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


uchar * const data = mat.data;

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = rows == 1 ? 0 : randomRow(generator);
//uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;











share|improve this question
















The following function will randomly "sprinkle salt" on a loaded image. For the sake of boosting performance, the conditional statement



uint j = rows == 1 ? 0 : randomRow(generator);


should not be inside the loop.



Instead, I want to define a lambda getJ before the loop as



auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


However, my code with this lambda does not compile with the following red squiggled text:



enter image description here



Question



How to conditionally define such a lambda?



void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);
uniform_int_distribution<uint> randomCol(0, cols - 1);



// auto getJ = rows == 1 ? []() return 0; : []() return randomRow(generator); ;


uchar * const data = mat.data;

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = rows == 1 ? 0 : randomRow(generator);
//uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;








c++






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 16 at 12:42







Artificial Hairless Armpit

















asked Apr 16 at 12:32









Artificial Hairless ArmpitArtificial Hairless Armpit

1,3441536




1,3441536







  • 3





    "my code with this lambda does not compile" - What is the error you get?

    – Suma
    Apr 16 at 12:35











  • You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

    – VTT
    Apr 16 at 12:36







  • 5





    Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

    – Artyer
    Apr 16 at 12:40






  • 2





    Is a conditional really a performance issue here? Have you profiled the code?

    – Jesper Juhl
    Apr 16 at 12:42






  • 1





    @Artyer Done well, the call to the lambda can be inlined.

    – Angew
    Apr 16 at 12:43












  • 3





    "my code with this lambda does not compile" - What is the error you get?

    – Suma
    Apr 16 at 12:35











  • You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

    – VTT
    Apr 16 at 12:36







  • 5





    Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

    – Artyer
    Apr 16 at 12:40






  • 2





    Is a conditional really a performance issue here? Have you profiled the code?

    – Jesper Juhl
    Apr 16 at 12:42






  • 1





    @Artyer Done well, the call to the lambda can be inlined.

    – Angew
    Apr 16 at 12:43







3




3





"my code with this lambda does not compile" - What is the error you get?

– Suma
Apr 16 at 12:35





"my code with this lambda does not compile" - What is the error you get?

– Suma
Apr 16 at 12:35













You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

– VTT
Apr 16 at 12:36






You are trying to reference local variable generator without capturing it. If second lambda was capture-free it would compile.

– VTT
Apr 16 at 12:36





5




5





Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

– Artyer
Apr 16 at 12:40





Seems like a premature optimisation. Surely function call overhead would be greater than ternary overhead?

– Artyer
Apr 16 at 12:40




2




2





Is a conditional really a performance issue here? Have you profiled the code?

– Jesper Juhl
Apr 16 at 12:42





Is a conditional really a performance issue here? Have you profiled the code?

– Jesper Juhl
Apr 16 at 12:42




1




1





@Artyer Done well, the call to the lambda can be inlined.

– Angew
Apr 16 at 12:43





@Artyer Done well, the call to the lambda can be inlined.

– Angew
Apr 16 at 12:43












2 Answers
2






active

oldest

votes


















10















my code with this lambda does not compile with the following red squiggled text




You cannot use randomRow inside the body of the lambda expression without capturing it beforehand, as the generated closure object needs to have access to it.



Even if you were to use [&randomRow], the code would still fail to compile as every lambda expression produces a closure of unique type, even if the lambda expressions are exactly the same.



You can turn the problem on its head to avoid any overhead and achieve what you want - create a function that takes the lambda you want to invoke:



template <typename F>
void saltImpl(F&& getJ, /* ... */)

uchar * const data = mat.data;

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = rows == 1 ? 0 : randomRow(generator);
//uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;




Usage example:



void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);
uniform_int_distribution<uint> randomCol(0, cols - 1);

if (rows == 1)

saltImpl([] return 0; , /* ... */);

else

saltImpl([&] return randomRow(generator); , /* ... */)







share|improve this answer




















  • 1





    Why not write a lambda that takes a lambda instead?

    – Yakk - Adam Nevraumont
    Apr 16 at 13:41


















3














Why this fails is because the lambdas are of a different type. That's natural, their operator() have different definitions. Which means you want your following code to work with two different types. And the C++ way of making code work with different types is using templates.



Convert the code using getJ to a function template (it can be local to your implementation file), like this:



template <class G>
void salt_impl_(Mat mat, unsigned long long n, default_random_engine &generator, G getJ)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


uchar * const data = mat.data;

uniform_int_distribution<uint> randomCol(0, cols - 1);

for (unsigned long long counter = 0; counter < n; counter++)

uint i = randomCol(generator);
uint j = getJ();

uint index = channels * (cols * j + i);
for (uchar k = 0; k < channels; k++)
data[index + k] = 255;




void salt_(Mat mat, unsigned long long n)

const uchar channels = mat.channels();
uint cols = mat.cols;
uint rows = mat.rows;

if (mat.isContinuous())

cols *= rows;
rows = 1;


default_random_engine generator;
uniform_int_distribution<uint> randomRow(0, rows - 1);

if (rows == 1)
salt_impl_(mat, n, generator, []() return 0; );
else
salt_impl_(mat, n, generator, [&]() return randomRow(generator); );



Feel free to reduce the initial-part duplication between the function and the template by passing more parameters, making them members of a class, or something similar.



Also note that the non-trivial lambda must capture the variables which it accesses (randomRow and generator). I did this using the universal by-reference capture [&] in the code above.






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55708242%2fhow-to-conditionally-define-a-lambda%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    10















    my code with this lambda does not compile with the following red squiggled text




    You cannot use randomRow inside the body of the lambda expression without capturing it beforehand, as the generated closure object needs to have access to it.



    Even if you were to use [&randomRow], the code would still fail to compile as every lambda expression produces a closure of unique type, even if the lambda expressions are exactly the same.



    You can turn the problem on its head to avoid any overhead and achieve what you want - create a function that takes the lambda you want to invoke:



    template <typename F>
    void saltImpl(F&& getJ, /* ... */)

    uchar * const data = mat.data;

    for (unsigned long long counter = 0; counter < n; counter++)

    uint i = randomCol(generator);
    uint j = rows == 1 ? 0 : randomRow(generator);
    //uint j = getJ();

    uint index = channels * (cols * j + i);
    for (uchar k = 0; k < channels; k++)
    data[index + k] = 255;




    Usage example:



    void salt_(Mat mat, unsigned long long n)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    default_random_engine generator;
    uniform_int_distribution<uint> randomRow(0, rows - 1);
    uniform_int_distribution<uint> randomCol(0, cols - 1);

    if (rows == 1)

    saltImpl([] return 0; , /* ... */);

    else

    saltImpl([&] return randomRow(generator); , /* ... */)







    share|improve this answer




















    • 1





      Why not write a lambda that takes a lambda instead?

      – Yakk - Adam Nevraumont
      Apr 16 at 13:41















    10















    my code with this lambda does not compile with the following red squiggled text




    You cannot use randomRow inside the body of the lambda expression without capturing it beforehand, as the generated closure object needs to have access to it.



    Even if you were to use [&randomRow], the code would still fail to compile as every lambda expression produces a closure of unique type, even if the lambda expressions are exactly the same.



    You can turn the problem on its head to avoid any overhead and achieve what you want - create a function that takes the lambda you want to invoke:



    template <typename F>
    void saltImpl(F&& getJ, /* ... */)

    uchar * const data = mat.data;

    for (unsigned long long counter = 0; counter < n; counter++)

    uint i = randomCol(generator);
    uint j = rows == 1 ? 0 : randomRow(generator);
    //uint j = getJ();

    uint index = channels * (cols * j + i);
    for (uchar k = 0; k < channels; k++)
    data[index + k] = 255;




    Usage example:



    void salt_(Mat mat, unsigned long long n)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    default_random_engine generator;
    uniform_int_distribution<uint> randomRow(0, rows - 1);
    uniform_int_distribution<uint> randomCol(0, cols - 1);

    if (rows == 1)

    saltImpl([] return 0; , /* ... */);

    else

    saltImpl([&] return randomRow(generator); , /* ... */)







    share|improve this answer




















    • 1





      Why not write a lambda that takes a lambda instead?

      – Yakk - Adam Nevraumont
      Apr 16 at 13:41













    10












    10








    10








    my code with this lambda does not compile with the following red squiggled text




    You cannot use randomRow inside the body of the lambda expression without capturing it beforehand, as the generated closure object needs to have access to it.



    Even if you were to use [&randomRow], the code would still fail to compile as every lambda expression produces a closure of unique type, even if the lambda expressions are exactly the same.



    You can turn the problem on its head to avoid any overhead and achieve what you want - create a function that takes the lambda you want to invoke:



    template <typename F>
    void saltImpl(F&& getJ, /* ... */)

    uchar * const data = mat.data;

    for (unsigned long long counter = 0; counter < n; counter++)

    uint i = randomCol(generator);
    uint j = rows == 1 ? 0 : randomRow(generator);
    //uint j = getJ();

    uint index = channels * (cols * j + i);
    for (uchar k = 0; k < channels; k++)
    data[index + k] = 255;




    Usage example:



    void salt_(Mat mat, unsigned long long n)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    default_random_engine generator;
    uniform_int_distribution<uint> randomRow(0, rows - 1);
    uniform_int_distribution<uint> randomCol(0, cols - 1);

    if (rows == 1)

    saltImpl([] return 0; , /* ... */);

    else

    saltImpl([&] return randomRow(generator); , /* ... */)







    share|improve this answer
















    my code with this lambda does not compile with the following red squiggled text




    You cannot use randomRow inside the body of the lambda expression without capturing it beforehand, as the generated closure object needs to have access to it.



    Even if you were to use [&randomRow], the code would still fail to compile as every lambda expression produces a closure of unique type, even if the lambda expressions are exactly the same.



    You can turn the problem on its head to avoid any overhead and achieve what you want - create a function that takes the lambda you want to invoke:



    template <typename F>
    void saltImpl(F&& getJ, /* ... */)

    uchar * const data = mat.data;

    for (unsigned long long counter = 0; counter < n; counter++)

    uint i = randomCol(generator);
    uint j = rows == 1 ? 0 : randomRow(generator);
    //uint j = getJ();

    uint index = channels * (cols * j + i);
    for (uchar k = 0; k < channels; k++)
    data[index + k] = 255;




    Usage example:



    void salt_(Mat mat, unsigned long long n)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    default_random_engine generator;
    uniform_int_distribution<uint> randomRow(0, rows - 1);
    uniform_int_distribution<uint> randomCol(0, cols - 1);

    if (rows == 1)

    saltImpl([] return 0; , /* ... */);

    else

    saltImpl([&] return randomRow(generator); , /* ... */)








    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Apr 16 at 12:49

























    answered Apr 16 at 12:42









    Vittorio RomeoVittorio Romeo

    59.8k17166310




    59.8k17166310







    • 1





      Why not write a lambda that takes a lambda instead?

      – Yakk - Adam Nevraumont
      Apr 16 at 13:41












    • 1





      Why not write a lambda that takes a lambda instead?

      – Yakk - Adam Nevraumont
      Apr 16 at 13:41







    1




    1





    Why not write a lambda that takes a lambda instead?

    – Yakk - Adam Nevraumont
    Apr 16 at 13:41





    Why not write a lambda that takes a lambda instead?

    – Yakk - Adam Nevraumont
    Apr 16 at 13:41













    3














    Why this fails is because the lambdas are of a different type. That's natural, their operator() have different definitions. Which means you want your following code to work with two different types. And the C++ way of making code work with different types is using templates.



    Convert the code using getJ to a function template (it can be local to your implementation file), like this:



    template <class G>
    void salt_impl_(Mat mat, unsigned long long n, default_random_engine &generator, G getJ)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    uchar * const data = mat.data;

    uniform_int_distribution<uint> randomCol(0, cols - 1);

    for (unsigned long long counter = 0; counter < n; counter++)

    uint i = randomCol(generator);
    uint j = getJ();

    uint index = channels * (cols * j + i);
    for (uchar k = 0; k < channels; k++)
    data[index + k] = 255;




    void salt_(Mat mat, unsigned long long n)

    const uchar channels = mat.channels();
    uint cols = mat.cols;
    uint rows = mat.rows;

    if (mat.isContinuous())

    cols *= rows;
    rows = 1;


    default_random_engine generator;
    uniform_int_distribution<uint> randomRow(0, rows - 1);

    if (rows == 1)
    salt_impl_(mat, n, generator, []() return 0; );
    else
    salt_impl_(mat, n, generator, [&]() return randomRow(generator); );



    Feel free to reduce the initial-part duplication between the function and the template by passing more parameters, making them members of a class, or something similar.



    Also note that the non-trivial lambda must capture the variables which it accesses (randomRow and generator). I did this using the universal by-reference capture [&] in the code above.






    share|improve this answer



























      3














      Why this fails is because the lambdas are of a different type. That's natural, their operator() have different definitions. Which means you want your following code to work with two different types. And the C++ way of making code work with different types is using templates.



      Convert the code using getJ to a function template (it can be local to your implementation file), like this:



      template <class G>
      void salt_impl_(Mat mat, unsigned long long n, default_random_engine &generator, G getJ)

      const uchar channels = mat.channels();
      uint cols = mat.cols;
      uint rows = mat.rows;

      if (mat.isContinuous())

      cols *= rows;
      rows = 1;


      uchar * const data = mat.data;

      uniform_int_distribution<uint> randomCol(0, cols - 1);

      for (unsigned long long counter = 0; counter < n; counter++)

      uint i = randomCol(generator);
      uint j = getJ();

      uint index = channels * (cols * j + i);
      for (uchar k = 0; k < channels; k++)
      data[index + k] = 255;




      void salt_(Mat mat, unsigned long long n)

      const uchar channels = mat.channels();
      uint cols = mat.cols;
      uint rows = mat.rows;

      if (mat.isContinuous())

      cols *= rows;
      rows = 1;


      default_random_engine generator;
      uniform_int_distribution<uint> randomRow(0, rows - 1);

      if (rows == 1)
      salt_impl_(mat, n, generator, []() return 0; );
      else
      salt_impl_(mat, n, generator, [&]() return randomRow(generator); );



      Feel free to reduce the initial-part duplication between the function and the template by passing more parameters, making them members of a class, or something similar.



      Also note that the non-trivial lambda must capture the variables which it accesses (randomRow and generator). I did this using the universal by-reference capture [&] in the code above.






      share|improve this answer

























        3












        3








        3







        Why this fails is because the lambdas are of a different type. That's natural, their operator() have different definitions. Which means you want your following code to work with two different types. And the C++ way of making code work with different types is using templates.



        Convert the code using getJ to a function template (it can be local to your implementation file), like this:



        template <class G>
        void salt_impl_(Mat mat, unsigned long long n, default_random_engine &generator, G getJ)

        const uchar channels = mat.channels();
        uint cols = mat.cols;
        uint rows = mat.rows;

        if (mat.isContinuous())

        cols *= rows;
        rows = 1;


        uchar * const data = mat.data;

        uniform_int_distribution<uint> randomCol(0, cols - 1);

        for (unsigned long long counter = 0; counter < n; counter++)

        uint i = randomCol(generator);
        uint j = getJ();

        uint index = channels * (cols * j + i);
        for (uchar k = 0; k < channels; k++)
        data[index + k] = 255;




        void salt_(Mat mat, unsigned long long n)

        const uchar channels = mat.channels();
        uint cols = mat.cols;
        uint rows = mat.rows;

        if (mat.isContinuous())

        cols *= rows;
        rows = 1;


        default_random_engine generator;
        uniform_int_distribution<uint> randomRow(0, rows - 1);

        if (rows == 1)
        salt_impl_(mat, n, generator, []() return 0; );
        else
        salt_impl_(mat, n, generator, [&]() return randomRow(generator); );



        Feel free to reduce the initial-part duplication between the function and the template by passing more parameters, making them members of a class, or something similar.



        Also note that the non-trivial lambda must capture the variables which it accesses (randomRow and generator). I did this using the universal by-reference capture [&] in the code above.






        share|improve this answer













        Why this fails is because the lambdas are of a different type. That's natural, their operator() have different definitions. Which means you want your following code to work with two different types. And the C++ way of making code work with different types is using templates.



        Convert the code using getJ to a function template (it can be local to your implementation file), like this:



        template <class G>
        void salt_impl_(Mat mat, unsigned long long n, default_random_engine &generator, G getJ)

        const uchar channels = mat.channels();
        uint cols = mat.cols;
        uint rows = mat.rows;

        if (mat.isContinuous())

        cols *= rows;
        rows = 1;


        uchar * const data = mat.data;

        uniform_int_distribution<uint> randomCol(0, cols - 1);

        for (unsigned long long counter = 0; counter < n; counter++)

        uint i = randomCol(generator);
        uint j = getJ();

        uint index = channels * (cols * j + i);
        for (uchar k = 0; k < channels; k++)
        data[index + k] = 255;




        void salt_(Mat mat, unsigned long long n)

        const uchar channels = mat.channels();
        uint cols = mat.cols;
        uint rows = mat.rows;

        if (mat.isContinuous())

        cols *= rows;
        rows = 1;


        default_random_engine generator;
        uniform_int_distribution<uint> randomRow(0, rows - 1);

        if (rows == 1)
        salt_impl_(mat, n, generator, []() return 0; );
        else
        salt_impl_(mat, n, generator, [&]() return randomRow(generator); );



        Feel free to reduce the initial-part duplication between the function and the template by passing more parameters, making them members of a class, or something similar.



        Also note that the non-trivial lambda must capture the variables which it accesses (randomRow and generator). I did this using the universal by-reference capture [&] in the code above.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Apr 16 at 12:42









        AngewAngew

        135k11261355




        135k11261355



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55708242%2fhow-to-conditionally-define-a-lambda%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            rH31cL4MSI,O907OCbcf k 2kaufa2Nr3ED38dph5I64LkjR8nkqwVk5GQ y0OR5gLaE W61nq8d2rMKkN1ifSR,f I4ED nFS3
            guHqO,Texjz,HbmgL0,5OMm ex9MblX8v2o1bGhs 4D7xQh9GpeN 0

            Popular posts from this blog

            RemoteApp sporadic failureWindows 2008 RemoteAPP client disconnects within a matter of minutesWhat is the minimum version of RDP supported by Server 2012 RDS?How to configure a Remoteapp server to increase stabilityMicrosoft RemoteApp Active SessionRDWeb TS connection broken for some users post RemoteApp certificate changeRemote Desktop Licensing, RemoteAPPRDS 2012 R2 some users are not able to logon after changed date and time on Connection BrokersWhat happens during Remote Desktop logon, and is there any logging?After installing RDS on WinServer 2016 I still can only connect with two users?RD Connection via RDGW to Session host is not connecting

            Vilaño, A Laracha Índice Patrimonio | Lugares e parroquias | Véxase tamén | Menú de navegación43°14′52″N 8°36′03″O / 43.24775, -8.60070

            Cegueira Índice Epidemioloxía | Deficiencia visual | Tipos de cegueira | Principais causas de cegueira | Tratamento | Técnicas de adaptación e axudas | Vida dos cegos | Primeiros auxilios | Crenzas respecto das persoas cegas | Crenzas das persoas cegas | O neno deficiente visual | Aspectos psicolóxicos da cegueira | Notas | Véxase tamén | Menú de navegación54.054.154.436928256blindnessDicionario da Real Academia GalegaPortal das Palabras"International Standards: Visual Standards — Aspects and Ranges of Vision Loss with Emphasis on Population Surveys.""Visual impairment and blindness""Presentan un plan para previr a cegueira"o orixinalACCDV Associació Catalana de Cecs i Disminuïts Visuals - PMFTrachoma"Effect of gene therapy on visual function in Leber's congenital amaurosis"1844137110.1056/NEJMoa0802268Cans guía - os mellores amigos dos cegosArquivadoEscola de cans guía para cegos en Mortágua, PortugalArquivado"Tecnología para ciegos y deficientes visuales. Recopilación de recursos gratuitos en la Red""Colorino""‘COL.diesis’, escuchar los sonidos del color""COL.diesis: Transforming Colour into Melody and Implementing the Result in a Colour Sensor Device"o orixinal"Sistema de desarrollo de sinestesia color-sonido para invidentes utilizando un protocolo de audio""Enseñanza táctil - geometría y color. Juegos didácticos para niños ciegos y videntes""Sistema Constanz"L'ocupació laboral dels cecs a l'Estat espanyol està pràcticament equiparada a la de les persones amb visió, entrevista amb Pedro ZuritaONCE (Organización Nacional de Cegos de España)Prevención da cegueiraDescrición de deficiencias visuais (Disc@pnet)Braillín, un boneco atractivo para calquera neno, con ou sen discapacidade, que permite familiarizarse co sistema de escritura e lectura brailleAxudas Técnicas36838ID00897494007150-90057129528256DOID:1432HP:0000618D001766C10.597.751.941.162C97109C0155020