2012-03-11 10 views
6

Pregunté this question anteriormente donde se presentó a solution. La solución es excelente en lo que respecta a la pregunta, pero ahora estoy confundido sobre cómo definiría los métodos fuera de de la clase, es decir, me gustaría definir los métodos en un archivo .inl. ¿Cuál sería la sintaxis en este caso?Definición de métodos de clase de plantilla con enable_if como parámetro de plantilla

Para que quede claro, para una clase de plantilla, la definición del método será:

template <typename T> 
struct Foo 
{ 
    Foo(); 
}; 

// C-tor definition 
template <typename T> 
Foo<T>::Foo() 
{ 
} 

¿cómo iba a definir los métodos de la clase de plantilla con enable_if como uno de los parámetros?

template <typename Policy, enable_if< is_base<BasePolicy, Policy>::value >::type > 
struct Foo 
{ 
  Foo(); 
}; 

// C-tor definition -- ??? 
+0

¿Lo mismo que haría si lo definiera en línea? ¿Cuál es el problema? –

+0

@KerrekSB: No estoy seguro de la sintaxis ... mis intentos actuales de extraer el constructor al archivo 'inl' resultaron en un error:' {ctor}: no es miembro de Foo '. La definición dentro de la propia estructura compila bien. – Samaursa

+1

Creo que el problema es que la "solución" publicada anteriormente no es realmente una solución: necesita extraer el tipo de 'enable_if <...>' o 'bool' de' enable_if_c <...> 'y usarlo como [predeterminado para] un parámetro de plantilla. Una vez hecho esto, queda claro cómo sería la definición de fuera de línea. –

Respuesta

9

Desde el aspecto de la misma, que quieren hacer algo en la línea de este:

template <typename Policy, 
      typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type > 
struct Foo; 

template <typename Policy> 
struct Foo<Policy> { 
    Foo(); 
}; 

template <typename Policy> 
Foo<Policy>::Foo() { 
} 

Esto lleva a escondidas ventaja del argumento por defecto en algunos lugares: no se confunda, hay una implícito void sentado en varios lugares.

+0

'is_base_of' es C++ 11 ... ¿es el razonamiento con el' void' implícito también una propiedad de C++ 11? Estoy obteniendo el mismo error que puse en otros comentarios ('error C2039: {ctor}: no es miembro de ...') – Samaursa

7

Así es como SFINAE en realidad puede trabajar con la especialización parcial:

template<typename T, typename Sfinae = void> 
struct Foo { 
    /* catch-all primary template */ 
    /* or e.g. leave undefined if you don't need it */ 
}; 

template<typename T> 
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> { 
    /* matches types derived from BasePolicy */ 
    Foo(); 
}; 

La definición de ese constructor puede introducirse entonces torpemente con:

template<typename T> 
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo() 
{ 
    /* Phew, we're there */ 
} 

Si su compilador soporta alias plantilla (es una característica de C++ 11) que luego puede cortar la mayor parte de la verborrea:

template<typename T> 
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type; 

// Somewhat nicer: 

template<typename T> 
struct Foo<T, EnableIfPolicy<T>> { 
    Foo(); 
}; 

template<typename T> 
Foo<T, EnableIfPolicy<T>>::Foo() {} 

Nota: su respuesta original se refería a las utilidades de Boost, como boost::enable_if_c y boost::is_base_of. Si está usando que en lugar de std::enable_if y std::is_base_of (que son de C++ 11), entonces el uso parece

typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type 

que tiene la ventaja de deshacerse de uno ::value.

+0

Gracias por la sintaxis. Sin embargo, no funciona para mí :(... obtengo: 'error C2039: {ctor}: no es miembro de ...' – Samaursa

+0

@Samaursa Lo siento mucho, compré que mi compilador acepte el fragmento, pero realmente no sé si de hecho es posible referirme a miembros de esa especialización parcial. Por lo tanto, no sé si el error de tu compilador está justificado o no. –

+0

Tu fragmento es 'C++ 11' aunque lo único diferente es el uso de 'std :: enable_if' vs.' boost :: enable_if'. No estoy seguro de por qué mi compilador (VC++ 2008) está rechazando la definición. – Samaursa

Cuestiones relacionadas