2011-01-21 16 views
8

Tengo una plantilla de clase y parece que no puedo encontrar la manera de realizar una instanciación de estilo de plantilla variable.VS2107 C++ plantilla variadic ejemplo

Aquí es el "código" en la medida de lo que estoy buscando:

template<typename _Classname, typename... Args> 
class CFunctorStartExT 
{ 
    friend class CXXFactory; 
protected: 
    template<typename U> 
    CFunctorStartExT(typename U& _functor, Args&... args) : 
    m_Functor(_functor), 
    m_args(args) 
    { 
    } 
    virtual bool ProcessLoop(CSomeClass* pThread) 
    { 
    return m_Functor(pThread, m_args); 
    } 

protected: 
    _Classname& m_Functor; 
    Args... m_args; 
}; 

Obviamente, esto no se compilará :). La idea es crear una clase que pueda almacenar los valores pasados ​​(si corresponde) podría tener _Classname/U defined) en el constructor para que luego se puedan recuperar y pasar a m_Functor en otra función.

Primero: ¿se puede hacer la plantilla variable incluso en VS2010? Estoy obteniendo problemas de compilación solo con la declaración de plantilla error C2143: syntax error : missing ',' before '...' de la línea template<typename _Classname, typename... Args>

En segundo lugar, ¿se puede hacer lo que estoy tratando de lograr? ¡Gracias!

+2

Los nombres que comienzan con un guión bajo seguido de una letra mayúscula, como '_Classname', están reservados y no debe usarlos en su programa. –

+0

oh ... ¿reservado para qué/quién? He intentado cambiar mi convención de nombres ... (cambio de m_, g_, etc.) – BabelFish

+1

Ver [esto] (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using -un-guión bajo-en-ac-identificador). – GManNickG

Respuesta

24

Visual C++ 2010 no admite plantillas variadic.

+0

lol .. bummer .. :(de todos modos para lograr lo que estoy haciendo a través de macros variadic? Sé que std :: make_shared tiene un estilo variado pero me pierdo en todas las definiciones. – BabelFish

+3

¿Eso significa que alguien en Microsoft hizo una gran cantidad de copiar y pegar para obtener una [clase tuple] limitada (http://msdn.microsoft.com/en-us/library/bb982837.aspx)? – Thomas

+1

no ... tienen este intrincado macro definir "mecanismo" que define e indefinidamente para crear las clases necesarias ... por lo que puedo decir. Lo ves en los archivos xxshared y xfwrap y xfwrap1 etc. – BabelFish

-2

Las plantillas de Variadic son un parche en un kludge después de un hack; no vas a disfrutar esto. La forma de hacerlo (fuera de mi cabeza) es usar la especialización de plantillas junto con la herencia. Algo a lo largo de estas líneas:

template<typename Classname, typename... Args> 
class CFunctorStartExT; 

template<typename Classname, typename Arg0, typename... Args> 
class CFunctorStartExT : private CFunctorStartExT<Classname, Args...> { 
protected: 
    Arg0 m_arg; 
}; 

template<typename Classname> 
class CFunctorStartExT { 
protected: 
    Classname &m_Functor; 
}; 

que nunca he hecho esto antes, y no lo he probado, pero esta es la idea general. Puede echar un vistazo a la implementación std::tuple para algo que realmente funciona.

3

Creo que lo siguiente hará lo que quiera. Lo primero que necesita una utilidad:

// make_tuple_indices 

template <size_t...> struct tuple_indices {}; 

template <size_t _Sp, class _IntTuple, size_t _Ep> 
struct make_indices_imp; 

template <size_t _Sp, size_t ..._Indices, size_t _Ep> 
struct make_indices_imp<_Sp, tuple_indices<_Indices...>, _Ep> 
{ 
    typedef typename make_indices_imp<_Sp+1, tuple_indices<_Indices..., _Sp>, _Ep>::type type; 
}; 

template <size_t _Ep, size_t ..._Indices> 
struct make_indices_imp<_Ep, tuple_indices<_Indices...>, _Ep> 
{ 
    typedef tuple_indices<_Indices...> type; 
}; 

template <size_t _Ep, size_t _Sp = 0> 
struct make_tuple_indices 
{ 
    static_assert(_Sp <= _Ep, "make_tuple_indices input error"); 
    typedef typename make_indices_imp<_Sp, tuple_indices<>, _Ep>::type type; 
}; 

entonces usted puede utilizar esto para ayudar a expandir una tupla que sostiene sus argumentos:

template<typename _Classname, typename... Args> 
class CFunctorStartExT 
{ 
    friend class CXXFactory; 
protected: 
    template<typename U> 
    CFunctorStartExT(U& _functor, Args&... args) : 
    m_Functor(_functor), 
    m_args(args...) 
    { 
    } 

    virtual bool ProcessLoop(CSomeClass* pThread) 
    { 
    return ProcessLoop(pThread, 
         typename make_tuple_indices<sizeof...(Args)>::type()); 
    } 

protected: 
    _Classname& m_Functor; 
    std::tuple<Args...> m_args; 

private: 
    template <std::size_t ...Indx> 
    bool ProcessLoop(CSomeClass* pThread, tuple_indices<Indx...>) 
    { 
     return m_Functor(pThread, std::get<Indx>(m_args)...); 
    } 
}; 

En cuanto al apoyo plantilla variadic VS2010: No tengo idea.

+0

Bienvenido a Stack Overflow! –

+2

esto sería genial si VS2010 pudiera soportar "typename". .. " – BabelFish

+0

Gracias esto resolvió un escenario bastante similar con el que necesitaba ayuda. ¿Estaría bien incluir tu código tuple_indices/make_tuple_indices en una biblioteca con licencia tipo MIT? La licencia se puede ver aquí: http://www.angelcode.com/angelscript/sdk/docs/manual/doc_license.html – Functastic

Cuestiones relacionadas