Inicializace typy členů šablony pro základní třídy v seznamech odvozené třídy Inicializátor

hlasů
11

Zde je několik kód nastiňuje problém jsem zápasí s. Finální problém (pokud g ++ se zabývá v současné době), je to, že: „Chyba:‚Foo-T‘nebyl deklarován v tomto rozsahu“ Při provádění Bar :: Bar (...) konstruktoru rutina. V opačném případě je problém Pokouším se učit svou cestu přes je jeden z nastavení typů členské základny třídy na základě argumentů předávaných do odvozené třídy konstruktoru pomocí šablon. Pokud by se způsob, jak nastavit typ člen základní třídy (T Foo-T) jednoduše předáním argumentů do odvozené-konstruktoru třídy, raději bych to. V tuto chvíli nevidím způsob, jak v minulosti za použití jak šablony argument, a odvozené třídy konstruktoru argument, odpovídající ke splnění tohoto úkolu. Dokážete najít něco v následujícím kódu, že mohu dělat lépe dosáhnout stejných cílů? Jsem generické-kódování a šablon poměrně nová.

#include <iostream>
typedef int a_arg_t;
typedef double b_arg_t;
typedef std::string foo_arg_t;

class TypeA {
public:
    TypeA ();
    TypeA (a_arg_t a) {
        /* Do sosmething with the parameter passed in */
    }

};

class TypeB {
public:
    TypeB ();
    TypeB (b_arg_t b) {
        /* typeB's constructor - do something here */
    }

};

// The base-class with a member-type to be determined by the template argument
template <class T>
class Foo {

public:
    Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg)       // initialize something here
    {
        /* do something for foo */
    }
    T Foo_T;        // either a TypeA or a TypeB - TBD
    foo_arg_t _foo_arg;
};

// the derived class that should set the basse-member type (T Foo_T)
template <class T>
class Bar : public Foo<T> {
public:
    Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
    : Foo<T>(bar_arg)   // base-class initializer
    {
        // the initialization of Foo_T has to be done outside the initializer list because it's not in scsope until here
        Foo_T = TypeA(a_arg);   // if an a_arg_t is passed in, then we set the Foo_T to TypeA, etc.
    }

    Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
    : Foo<T>(bar_arg)
    {
        Foo_T = TypeB(b_arg);
    }

};

int main () {

    b_arg_t b_arg;
    a_arg_t a_arg;
    foo_arg_t bar_arg;

    Bar<TypeA> a (bar_arg, a_arg);  // try creating the derived class using TypeA
    Bar<TypeB> b (bar_arg, b_arg); // and another type for show

return 0;
}
Položena 13/07/2009 v 05:24
zdroj uživatelem
V jiných jazycích...                            


3 odpovědí

hlasů
3

Líto, že neužitečné, ale taky nevidím způsob, jak vyřešit tento problém, aniž by dělali přesně to, co je uvedeno:

V tuto chvíli nevidím způsob, jak v minulosti za použití jak šablony argument, a odvozené třídy konstruktoru argument, odpovídající ke splnění tohoto úkolu.

Budete pravděpodobně muset specializovat trochu:

template<>
Bar<TypeA>::Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<TypeA>(bar_arg)   // base-class initializer
{
    // the initialization of Foo_T has to be done outside the initializer list because it's not in scsope until here
    Foo_T = TypeA(a_arg);   // if an a_arg_t is passed in, then we set the Foo_T to TypeA, etc.
}

template< class T>
Bar<T>::Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg)   // base-class initializer
{
    // Throw exception?
}

template<>
Bar<TypeB>::Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<TypeB>(bar_arg)
{
    Foo_T = TypeB(b_arg);
}

template< class T >
Bar<T>::Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
: Foo<T>(bar_arg)
{
    // Throw exception ?
}

Bohužel, nemám přístup k kompilátoru v okamžiku, kdy pro kontrolu tohoto kódu, takže se na pozoru.


V odpovědi na vaši otázku / komentář. Mám následující kompilaci:

#include <iostream>
typedef int a_arg_t;
typedef double b_arg_t;
typedef std::string foo_arg_t;

class TypeA {
public:
  TypeA () {}
  TypeA (a_arg_t a) {}
};

class TypeB {
public:
  TypeB () {}
  TypeB (b_arg_t b) {}
};

template <class T>
class Foo {
public:
  Foo (const foo_arg_t foo_arg) : _foo_arg(foo_arg) {}
  T Foo_T;        // either a TypeA or a TypeB - TBD
  foo_arg_t _foo_arg;
};

// the derived class that should set the basse-member type (T Foo_T)
template <class T>
class Bar : public Foo<T> {
public:
  Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
  : Foo<T>(bar_arg)   // base-class initializer
  {
    Foo<T>::Foo_T = TypeA(a_arg);
  }

  Bar (const foo_arg_t bar_arg, const b_arg_t b_arg)
  : Foo<T>(bar_arg)
  {
    Foo<T>::Foo_T = TypeB(b_arg);
  }
};

int main () {
  b_arg_t b_arg;
  a_arg_t a_arg;
  foo_arg_t bar_arg;

  Bar<TypeA> a (bar_arg, a_arg);  // try creating the derived class using TypeA
  Bar<TypeB> b (bar_arg, b_arg); // and another type for show

  return 0;
}
Odpovězeno 13/07/2009 v 05:37
zdroj uživatelem

hlasů
0

Když jsem se poprvé podíval na váš kód, byl jsem absolutně jistý, že budete muset vyřešit problém s částečnou specializací. Ve skutečnosti, že stále může být případ, nicméně jsem se snižuje množství kódu potřebného replikovat svou chybu, a zjistili, že došlo k chybě dochází pouze při kompilaci GCC (nevím, jakou verzi kompilátor má vysokoškolské běží ačkoli ), a při sestavování s Visual Studio 2003 - everythying jsou šťastní.

Vkládá se replikuje chybový kód, ale menší, zdánlivě nevinný změna překvapivě jej odstranit:

template <typename T>
class ClassA
{
public:
    ClassA () {}
    T vA;
};


template<typename T>
class ClassB : public ClassA<T>
{
public:
    ClassB ()
    {
        vA = 6;
    }
};

int main ()
{
    ClassB<int> cb;
}

Nyní, pokud odebrat deklaraci šablony z ClassB, a mít ji přímo dědí z Classa:

class ClassB : public ClassA<int>
{
public:
    ClassB ()
    {
        vA = 6;
    }
};

a pak změnit prohlášení centrální banky tak, aby odpovídala

    ClassB cb;

Pak zmizí chyba, i když tam je jasně nic liší, pokud jde o rozsah VA (nebo v případě, Foo_T)

Jsem spekulují, že se jedná o kompilátor chyba, a uvažoval, jestli snad zcela aktuální gcc kompilátor by ještě vyskytnout problém.

Odpovězeno 13/07/2009 v 07:55
zdroj uživatelem

hlasů
14

Typ Foo_T nebude vzhlédl v základní třídě při použití v odvozené (bar) konstruktoru.

Bar (const foo_arg_t bar_arg, const a_arg_t a_arg)
: Foo<T>(bar_arg)   // base-class initializer
{
    Foo_T = TypeA(a_arg);   TypeA, etc. // Won't compile, per the standard
}

To je podle Standard C ++, který říká, nekvalifikované názvy jsou obecně non-závislý, a je třeba se podívat, když je šablona plně definovány.

Vzhledem k tomu, definice šablony základní třídy není známo, v té době (tam mohl být plně specializované instance šablony vtažení později v kompilaci jednotky), nekvalifikované názvy nikdy vyřešen jmen v závislých základních tříd.

Potřebujete-li jména ze základní třídy, kdy jsou zapojeny šablony, budete muset buď plně kvalifikují, nebo aby byly implicitně závislé v odvozené třídě.

 Foo< T >::Foo_T = TypeA(a_arg);   // fully qualified will compile

nebo, aby to závisí

 this->Foo_T = TypeA(a_arg);

Vzhledem k tomu thisje, že šablony závislý, řešení typu je odloženo až do „fáze 2“ z instance šablony (a pak se základní třídy je také plně znám)

Všimněte si, že pokud jste chtěli použít funkci ze základní třídy, mohli byste mít také přidal pomocí prohlášení ..

(Uvnitř baru ())

  some_foo_func(); // wouldn't work either

  using Foo<T>::some_foo_func;
  some_foo_func(); // would work however
Odpovězeno 13/07/2009 v 10:20
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more