【问题标题】:Class templated member function and return type inference类模板化成员函数和返回类型推断
【发布时间】:2015-08-05 06:56:36
【问题描述】:

我想使用 C++11 自动小说明符来推断我的返回类型,但我尝试使用它的示例与它的典型用法有点不同。

我有一个基类和派生某些成员函数的子类。

enum class state {composite1, composite2, composite3};
class material
{
public:

}
class sub_material1 : material
{
public:
 template<typename T>
 T* transform(state to_state)
 {
 T* material;
   switch(to_state){
      case(state::composite1) :
         //do transform computations
         // set material to return
         material = some_transformed_material;
         break;
      case(state::composite2):
         // do transform computation
         // set material to return
         material = some_transformed_material;
         break;
.
.
.
.
}
return material;
}
}

所以如果我有类似的东西

sub_material1 mat1;
sub_material2 mat2;

mat2 = mat1.transform(state::composite2);

在这种情况下,我如何使用 auto 和 decltype ,因为我有条件测试可能会很长...... decltype 似乎有点过头了?

如何推断类型?

谢谢

【问题讨论】:

  • 你能创建完整的例子吗?什么是 some_transformed_material?

标签: c++ templates c++11


【解决方案1】:

此代码不起作用。编译器不能根据返回类型推断模板参数,所以你应该手动设置:

auto mat2 = mat1.transform<sub_material2>(state::composite2);

如果之前声明了 mat2:

sub_material2 *mat2;
mat2 = mat1.transform<sub_material2>(state::composite2);

您正在尝试混合指针和非指针类型。

我建议您尝试以下方法:

struct composite1 {};
struct composite2 {};
struct composite3 {};

class material
{
public:

}

class sub_material1 : material
{
public:
sub_material1 transform(composite1)
{
        //do transform computations
        // set material to return
        return some_transformed_material;
}

sub_material2 transform(composite2)
{
        //do transform computations
        // set material to return
        return some_transformed_material;
}
.
.
.
.
}

然后你可以这样:

sub_material1 mat1;
auto mat2 = mat1.transform(composite2{});

sub_material1 mat1;
sub_material2 mat2;

mat2 = mat1.transform(composite2{});

如果你愿意,你可以返回指针,但是 mat2 应该是 sub_material2* 类型的。

【讨论】:

    【解决方案2】:

    如果你想要的也是以下:

    sub_material3 ma3 ;
    mat3 = mat1.transform(state::composite3)
    

    那么答案是:你不能。编译器必须在编译时知道要调用哪个版本的转换。你可以这样做:

    template <enum class state>
    struct state_material
    {
        typedef type sub_material1 ;
    } ;
    

    然后专攻

    template <>
    struct state_material<state::composite1>
    {
        typedef type sub_material1 ;
    } ;
    
    template <>
    struct state_material<state::composite2>
    {
        typedef type sub_material2 ;
    } ;
    
    template <>
    struct state_material<state::composite3>
    {
        typedef type sub_material3 ;
    } ;
    

    然后这样调用:

    mat2 = mat1.template transform<state_material<state::composite2>::type>()
    

    【讨论】:

    • 我认为你不需要 template 来消除歧义,但我可能错了。
    【解决方案3】:

    当前形式的代码根本不起作用,autodecltype 在这里都没有多大帮助。编译器无法推断 T 的实际类型是什么。所以你必须在调用transform时指定该类型是什么:

    mat2 = mat1.transform<sub_material2>(state::composite2);
    

    但是,仍然存在一个问题:transform 返回一个T*,而不是T,即除非您将mat2 声明为sub_material2* 类型,否则分配将不起作用。

    如果该方法可以根据运行时参数返回不同类型的材料,您将不得不例如返回一个指向基类material 的对象的指针。模板用于做出编译时决策,但您的方法看起来像是在做出运行时决策!

    【讨论】:

      猜你喜欢
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      相关资源
      最近更新 更多