C++ 在派生类初始值设定项列表中初始化模板基类成员类型

C++ 在派生类初始值设定项列表中初始化模板基类成员类型,c++,inheritance,templates,initialization,C++,Inheritance,Templates,Initialization,下面是一些代码,概述了我一直在努力解决的一个问题。最后一个问题(就目前g++而言)是:“执行Bar::Bar(…)构造函数例程时,错误:'Foo-T'未在此范围内声明”。否则,我试图了解的问题是基于使用模板传递给派生类构造函数的参数设置基类成员类型。如果有一种简单地通过向派生类构造函数传递参数来设置基类成员类型(tfoo-T)的方法,我更愿意这样做。到目前为止,我还看不到同时使用模板参数和匹配的派生类构造函数参数来完成此任务的方法。你能在下面的代码中发现我可以做得更好的东西来实现同样的目标吗?我

下面是一些代码,概述了我一直在努力解决的一个问题。最后一个问题(就目前g++而言)是:“执行Bar::Bar(…)构造函数例程时,错误:'Foo-T'未在此范围内声明”。否则,我试图了解的问题是基于使用模板传递给派生类构造函数的参数设置基类成员类型。如果有一种简单地通过向派生类构造函数传递参数来设置基类成员类型(tfoo-T)的方法,我更愿意这样做。到目前为止,我还看不到同时使用模板参数和匹配的派生类构造函数参数来完成此任务的方法。你能在下面的代码中发现我可以做得更好的东西来实现同样的目标吗?我对通用编码和模板相当陌生

#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;
}
#包括
typedef int a_参数;
类型定义双b_参数;
typedef std::字符串foo_参数;
A类{
公众:
TypeA();
a型(a_参数a){
/*对传入的参数执行sosmeting*/
}
};
B类{
公众:
b型();
类型b(b_参数b){
/*typeB的构造函数-在这里做点什么*/
}
};
//成员类型由模板参数确定的基类
模板
福班{
公众:
Foo(const Foo\u arg\u t Foo\u arg):\u Foo\u arg(Foo\u arg)//在这里初始化一些东西
{
/*为福做点什么*/
}
T Foo_T;//类型a或类型B-待定
富阿格富阿格;
};
//应设置basse成员类型(T Foo\u T)的派生类
模板
分类栏:公共食品{
公众:
Bar(常量foo_arg_t Bar_arg,常量a_arg_t a_arg)
:Foo(bar_arg)//基类初始值设定项
{
//Foo_T的初始化必须在初始值设定项列表之外完成,因为在这里之前它不在scsope中
Foo_T=TypeA(a_arg);//如果传入a_arg,那么我们将Foo_T设置为TypeA,等等。
}
Bar(常数foo_arg_t Bar_arg,常数b_arg_t b_arg)
:Foo(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 a(Bar_arg,a_arg);//尝试使用TypeA创建派生类
Bar b(Bar_arg,b_arg);//和另一种用于显示的类型
返回0;
}

很抱歉我帮不上忙,但如果不完全按照您所说的做,我也看不到解决问题的办法:

到目前为止,我看不出有什么方法可以使用 模板参数和 匹配派生类构造函数 完成这项任务的理由

您可能需要专门化一点:

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 ?
}
模板
Bar::Bar(常量foo_arg_t Bar_arg,常量a_arg_t a_arg)
:Foo(bar_arg)//基类初始值设定项
{
//Foo_T的初始化必须在初始值设定项列表之外完成,因为在这里之前它不在scsope中
Foo_T=TypeA(a_arg);//如果传入a_arg,那么我们将Foo_T设置为TypeA,等等。
}
模板
Bar::Bar(常量foo_arg_t Bar_arg,常量a_arg_t a_arg)
:Foo(bar_arg)//基类初始值设定项
{
//抛出异常?
}
模板
Bar::Bar(常量foo_arg_t Bar_arg,常量b_arg_t b_arg)
:Foo(bar_arg)
{
Foo_T=TypeB(b_arg);
}
模板
Bar::Bar(常量foo_arg_t Bar_arg,常量b_arg_t b_arg)
:Foo(bar_arg)
{
//抛出异常?
}
不幸的是,我目前无法访问编译器来检查这段代码,所以要小心


回答你的问题/评论。我需要编译以下内容:

#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;
}
#包括
typedef int a_参数;
类型定义双b_参数;
typedef std::字符串foo_参数;
A类{
公众:
TypeA(){}
类型a(a_arg_t a){}
};
B类{
公众:
类型b(){}
类型b(b_arg_t b){}
};
模板
福班{
公众:
Foo(const Foo_arg_t Foo_arg):\u Foo_arg(Foo_arg){}
T Foo_T;//类型a或类型B-待定
富阿格富阿格;
};
//应设置basse成员类型(T Foo\u T)的派生类
模板
分类栏:公共食品{
公众:
Bar(常量foo_arg_t Bar_arg,常量a_arg_t a_arg)
:Foo(bar_arg)//基类初始值设定项
{
Foo::Foo_T=TypeA(a_arg);
}
Bar(常数foo_arg_t Bar_arg,常数b_arg_t b_arg)
:Foo(bar_arg)
{
Foo::Foo_T=TypeB(b_arg);
}
};
int main(){
b_arg_t b_arg;
a_arg_t a_arg;
foo_arg_t bar_arg;
Bar a(Bar_arg,a_arg);//尝试使用TypeA创建派生类
Bar b(Bar_arg,b_arg);//和另一种用于显示的类型
返回0;
}

当我第一次查看您的代码时,我完全确定您必须使用部分专业化来解决问题。事实上,情况可能仍然如此,但是,我已经减少了复制错误所需的代码量,并且注意到只有在使用gcc编译时(我不知道我的大学正在运行哪个编译器版本),以及在使用Visual Studio 2003编译时,才会发生错误-一切都很高兴

下面复制了错误代码,但一个微小的、看似无辜的更改将令人惊讶地消除它:

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;
}
然后错误消失,即使vA的范围(或者在您的案例中,Foo_T)显然没有什么不同


我推测这是一个编译器错误,并想知道是否一个完全更新的gcc编译器仍然会遇到这个问题。

当在派生(Bar)构造函数中使用时,不会在基类中查找Foo\u T类型

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
}
由于
this
使其依赖于模板,因此解析类型将推迟到模板实例化的“阶段2”(然后,基类也将完全已知)

请注意,如果要使用基类中的函数,还可以添加一个using声明

(内杆())

some_foo_func();//也不行
使用Foo::some_Foo_func;
一些_foo_func();//不过,这也行

你知道编译器错误是怎么说的吗_
    ClassB cb;
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
}
 Foo< T >::Foo_T = TypeA(a_arg);   // fully qualified will compile
 this->Foo_T = TypeA(a_arg);
  some_foo_func(); // wouldn't work either

  using Foo<T>::some_foo_func;
  some_foo_func(); // would work however