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
Can an iPhone 7 be made to function as a NFC Tag?
Are the endpoints of the domain of a function counted as critical points?
Is CEO the "profession" with the most psychopaths?
What is the difference between a "ranged attack" and a "ranged weapon attack"?
Why datecode is SO IMPORTANT to chip manufacturers?
Special flights
What is the origin of 落第?
One-one communication
What are the main differences between Stargate SG-1 cuts?
Found this skink in my tomato plant bucket. Is he trapped? Or could he leave if he wanted?
My mentor says to set image to Fine instead of RAW — how is this different from JPG?
"klopfte jemand" or "jemand klopfte"?
Is there hard evidence that the grant peer review system performs significantly better than random?
Mounting TV on a weird wall that has some material between the drywall and stud
How can a team of shapeshifters communicate?
Why is it faster to reheat something than it is to cook it?
How to write capital alpha?
The test team as an enemy of development? And how can this be avoided?
What initially awakened the Balrog?
Why complex landing gears are used instead of simple,reliability and light weight muscle wire or shape memory alloys?
Did any compiler fully use 80-bit floating point?
RSA find public exponent
Asymptotics question
How to ternary Plot3D a function
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;
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:
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++
|
show 7 more comments
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:
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++
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 variablegenerator
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
|
show 7 more comments
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:
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++
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:
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++
c++
edited Apr 16 at 12:42
Artificial Hairless Armpit
asked Apr 16 at 12:32
Artificial Hairless ArmpitArtificial Hairless Armpit
1,3261536
1,3261536
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 variablegenerator
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
|
show 7 more comments
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 variablegenerator
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
|
show 7 more comments
2 Answers
2
active
oldest
votes
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); , /* ... */)
1
Why not write a lambda that takes a lambda instead?
– Yakk - Adam Nevraumont
Apr 16 at 13:41
add a comment |
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.
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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); , /* ... */)
1
Why not write a lambda that takes a lambda instead?
– Yakk - Adam Nevraumont
Apr 16 at 13:41
add a comment |
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); , /* ... */)
1
Why not write a lambda that takes a lambda instead?
– Yakk - Adam Nevraumont
Apr 16 at 13:41
add a comment |
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); , /* ... */)
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); , /* ... */)
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
add a comment |
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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered Apr 16 at 12:42
AngewAngew
135k11261355
135k11261355
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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