简体   繁体   中英

Class templated member function and return type inference

I wanted to use the C++11 auto little specifier to deduce my return type , but the example in which i am trying to use it is a little different than its typical use.

I have a base class , and subclasses that derive certain member functions.

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;
}
}

so if i had something like

sub_material1 mat1;
sub_material2 mat2;

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

how can i use auto and decltype in this case given the fact that i have condition to test that can be very lengthy....decltype seems an overkill ?

How can the type be inferred ?

Thank you

This code will not work. Compiler can't deduce template argument based on return type, so you should set in manually:

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

if mat2 was declared before:

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

You are trying to mix pointer and non pointer type.

I suggest you to try the following:

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;
}
.
.
.
.
}

then you can something like this:

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

or

sub_material1 mat1;
sub_material2 mat2;

mat2 = mat1.transform(composite2{});

You can return pointer if you like, but then mat2 should by of type sub_material2*.

If what you want is also the following:

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

then the answer is: you can't. The compiler has to know at compile time which version of transform to call. You can do something like this:

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

and then specialize

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 ;
} ;

Then call like this:

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

The code in its current form won't work at all, and neither auto nor decltype are going to help much here. The compiler can't infere what the actual type of T is. So you would have to specify what that type is when calling transform :

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

However, there is still a problem: transform returns a T* , not a T , ie the assignment won't work unless you declared mat2 to be of type sub_material2* .

If the method could return different types of materials based on a runtime parameter, you would have to eg return a pointer to an object of the base class material . Templates are for making compile-time decisions, but your method looks like it makes a runtime decision!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM