
Muitas vezes precisamos implementar uma função sob demanda, ou seja, passar parâmetros de acordo com a necessidade do nosso aplicativo. E o std::placeholders servem para isso.
O namespace std::placeholders trabalha juntamente com a função std::bind e precisamos incluir o cabeçalho <funcional> para poder utilizarmos. Eles contém os objetos de placeholder [_1,..._N] onde N é um número máximo definido pela implementação.
O template de função std::bind retorna um objeto de função com base em fn, mas com seus argumentos vinculados a args.
Quando usado como um argumento em uma expressão std::bind, os objetos de espaço reservado são armazenados no objeto de função gerado e quando esse objeto de função é chamado com argumentos não acoplados, cada espaço reservado _N é substituído pelo enésimo argumento não acoplado correspondente.
extern /* não especificada */ _1; // até o c++17;inline constexpr /* não especificada */ _1;extern /* não especificada */ _1; , ainda é permitido pelo padrão;DefaultConstructible e CopyConstructible_N, o tipo std::is_placeholder<decltype(_N)>;std::integral_constant<int, N>._1Dada a função soma_sub(int, int, int) que retorna a soma e subtração dos parâmetros, respectivamente, se quisermos que um parâmetro seja dinâmico:
Terceiro parâmetro dinâmico
#include <iostream>
#include <functional> // para std::placeholders e std::bind
using namespace std::placeholders;
int soma_sub( int x, int y, int z ){
return x + y - z;
}
int main( int argc , char **argv ){
// substitui o z
auto fn = std::bind( soma_sub, 9, 1, _1 );
std::cout << fn( 2 ) << '\n'; // equivale soma_sub( 9, 1, 2 ) = 8
std::cout << fn( 3 ) << '\n'; // equivale soma_sub( 9, 1, 3 ) = 7
return 0;
}
Substitui o
y
auto f2 = std::bind( soma_sub, 9, _1, 1 );
std::cout << f2( 2 ) << '\n'; // equivale soma_sub( 9, 2, 1 ) = 10
std::cout << f2( 3 ) << '\n'; // equivale soma_sub( 9, 3, 1 ) = 11Substitui o
x
auto f3 = std::bind( soma_sub, _1, 9, 1 );
std::cout << f3( 2 ) << '\n'; // equivale soma_sub( 2, 9, 1 ) = 10
std::cout << f3( 3 ) << '\n'; // equivale soma_sub( 3, 9, 2 ) = 11Substitui o
ye oz, respectivamente_1e_2. Como estamos usando o parâmetro_2, precisamos passar 2 parâmetros, caso contrário gera erro ao compilar.
auto f4 = std::bind( soma_sub, 1, _1, _2 );
std::cout << f4( 1, 2 ) << '\n'; // equivale soma_sub( 1, 1, 2 ) = 1 + 1 - 2 = 0
std::cout << f4( 3, 10 ) << '\n'; // equivale soma_sub( 1, 3, 10 ) = 1 + 3 - 10 = -6Substitui o
ze oy, respectivamente_2e_1
auto f5 = std::bind( soma_sub, 1, _2, _1 );
std::cout << f5( 1, 2 ) << '\n'; // equivale soma_sub( 1, 2, 1 ) = 1 + 2 - 1 = 2
std::cout << f5( 3, 10 ) << '\n'; // equivale soma_sub( 1, 10, 3 ) = 1 + 10 - 3 = 8
_2 = y,x = 1,z = 3. Tem que passar 2 parâmetros(senão não compila), mas o 1º será ignorado!
auto f6 = std::bind( soma_sub, 1, _2, 3 );
// | |_________________________________
// | |
// |__________________________________ |
// | |
// ignorado | |
// ↓ | |
std::cout << f6( 897, 0/* _2 */ ) << '\n'; // equivale soma_sub( 1, 0, 3 ) = 1 + 0 - 3 = -2
// ignorado
// ↓
std::cout << f6( 800, 2/* _2 */ ) << '\n';// equivale soma_sub( 1, 2, 0 ) = 1 + 2 - 0 = 2
Pra entender de vez!
x = _3, precisa informar 3 parâmetros(senão não compila), pois está usando o_3, mas os dois primeiros serão ignorados.
auto f7 = std::bind( soma_sub, _3, 1, 3 );
std::cout << f7( 0, 0, 30 ) << '\n'; // z = 8 , equivale soma_sub( 1, 3, 8 ) = 30 + 1 - 3 = 28Nova função de nome
show_name( std::string & )
#include <iostream>
#include <functional>
namespace pl = std::placeholders;
void show_name( std::string &name ){
std::cout << name << '\n';
}
int main( int argc , char **argv ){
std::string name("Olá, marcadores de posição");
auto fn1 = std::bind( show_name, pl::_1 );
fn1( name );
return 0;
}autostd::function<void( std::string & )> fn2 = std::bind( show_name , pl::_1 );
name = "Like, a boss!"; // declarada e inicializada no exemplo anterior!
fn2( name );namespaceExemplo final sem explicações, exercício!
#include <iostream>
#include <functional>
int add3(int x1, int x2, int x3) {
return x1 + x2 + x3;
}
int main( int argc , char **argv ){
auto fadd3 = std::bind(add3, 11, std::placeholders::_1, std::placeholders::_2);
std::cout << fadd3(22, 33) << '\n';
return 0;
}Curiosidades: Se você o
std::bindpuro, ele pode lhe dar um resultado incorreto. Outra coisa também é se você usa obindda libboost:boost::bindnão é compatível com astd::bind.
Então se inscreva nos nossos Cursos de C++ Moderno . Você aprender criar:
Acesse o endereço: