2010-11-29 20 views
10

No hace falta explicar más. El código siguiente es evidente:Cómo enlazar un constructor en C++?

struct X 
{ 
    X(int n){} 
}; 

int main() 
{ 
    std::vector<int> src; 
    std::vector<X> dest; 

    // Below is not valid in current C++, but that is just what I want. 
    transform(src.begin(), src.end(), back_insert(dest), std::bind(&X::X, _1)); 
} 

Un constructor toma algunos argumentos y devuelve un objeto de la clase del constructor.

Un constructor parece una función, actúa como una función y es exactamente una función.

Por lo tanto, creo que std :: bind debe tratar uniformemente los constructores y otros objetos invocables.

Sin embargo, ¿cómo puedo extender la plantilla de función "vincular" para implementar eso?

+3

Un constructor parece una función sin un tipo de retorno y con alguna sintaxis especial (inicializador de ctor), actúa como una función, pero no es exactamente una función. –

+0

Un constructor es una función, ese no es el problema. El problema es obtener una función _pointer_ para ello. '& X :: X' simplemente no es una expresión válida. – MSalters

+0

[Usando boost :: bind con un constructor] (http://stackoverflow.com/q/1335301/511601) –

Respuesta

14

desde X es implícitamente construible de int, una simple copia debe lograr la conversión.

copy(src.begin(), src.end(), std::back_inserter(dest)); 

O incluso utilizando el constructor del vector:

std::vector<X> dest(src.begin(), src.end()); 

En el caso general, impulso de lambda library tiene un funtor constructor.

#include <boost/lambda/bind.hpp> 
#include <boost/lambda/construct.hpp> 
... 
using namespace boost::lambda; 
transform(src.begin(), src.end(), std::back_inserter(dest), bind(constructor<X>(), _1)); 

En este caso particular, el enlace puede no ser necesario, ya que solo hay un argumento para el constructor.

+0

Gracias, visitante. Tu solución es exactamente lo que quiero. – xmllmx

+8

Me entristeció ver que esto no aborda 'std :: bind'. –

3

Un constructor es una función miembro.

Una función miembro necesita un objeto al que vincularse.

Un constructor solo se llama para un objeto que aún no existe, por lo que nunca puede haber un objeto para enlazar al constructor.

En su caso, los argumentos del constructor (los valores int de src) deberían ir a (un posible) back_inserter que llama al ctor no predeterminado y no a std :: transform. (EDIT: esto sólo es cierto para uso no-copia-ctor)

En realidad, lo que quiere hacer aquí es llamar std :: copia:

std::copy(src.begin(), src.end(), std::back_inserter(dest)); 
+0

¿Puedes dar el código de muestra, por favor? – frast

+0

Sé que hay muchas maneras de implementar lo que quiero hacer en el código de ejemplo. Sin embargo, quiero saber cómo hacer que bind trate a un constructor solo como una función. Porque un constructor puede tomarse como una función de conversión de tipo. – xmllmx

6

No sé si hay más fresco maneras Boost, pero se podría escribir algo como esto:

class Builder 
{ 
    X operator() (int value) const { return X(value); } 
}; 

transform(src.begin(), src.end(), back_insert(dest), Builder()); 
+0

Esta es una solución trivial y no es lo que quiero. Espero implementar eso extendiendo bind. En otras palabras, no necesito definir otra clase de objeto de función para cada caso. – xmllmx

+4

No puedo ver qué pasa con la solución * trivial * si funcionan. ¿Siempre necesitamos escribir cosas complejas? – Simone

+0

Consulte la solución para visitantes anterior. Eso es exactamente lo que quiero. – xmllmx

0

Un constructor toma algunos argumentos y devuelve un objeto de la clase del constructor.

No, un constructor no devuelve nada, y no existe un puntero a un constructor.

+0

X v1; v1 = X (8); // X (8) devuelve un objeto de la clase X – xmllmx

+3

@xmllmx: No, no lo hace, realmente. C++ tiene una definición muy clara de muchos términos, como "regresar". 'X (8)' es una expresión, y _hace_ tipo 'X'. Las expresiones no "devuelven" cosas ya que ni siquiera podrían ser funciones. Es decir. la expresión '3 + 4' no es una llamada a función. – MSalters

+0

la expresión 3 + 4 no es una llamada a función. ??? ¿No es igual a operador + (3, 4)? – xmllmx

0

Crea una función de fábrica. Estas son funciones miembro estáticas o funciones independientes que también construyen objetos, generalmente después de validar las entradas. Son útiles siempre que quiera asegurarse de que sus objetos no se puedan construir con entradas no válidas (después de todo, no puede cancelar la construcción dentro de un ctor).

Dado que una fábrica es una función normal, puede enlazarla fácilmente para obtener el mismo efecto que parece querer: una función vinculada que crea objetos.

class X 
{ 
public: 
    X(OtherObject a, OtherData data); 
    virtual ~X() {} 
}; 

// Factory- return "X" instead of "X*" if not using the heap 
X* CreateX(OtherObject a, OtherData data) { 
    /* 
     Logic that checks a, data for validity... 
    */ 
    if(invalid) { 
     return 0; // You get no object 
    } 
    return new X(); 
} 

Ahora solo tiene que enlazar a "CreateX" para crear objetos. Sin embargo, es una función normal, no un constructor, por lo que se aplican todas las reglas normales para funciones, especialmente aquellas para la construcción de objetos de copia y movimiento.