1

I am trying to set the fields inside struct dynamically using templates. I have wrote the two approaches in the code. Both methods don't work saying no member named t.age. How would I be able to set the fields dynamically? Any help is appreciated.

#include <iostream> 

using namespace std; 

struct hello { 
    string name; 
}; 

struct bye { 
    int age; 
}; 

template <typename T>  
void printHello(string key) { 
    T t;  
    if (key == "HELLO") { 
        t.name = "John"; 
    }   
    else { 
        t.age = 0;  
    }   
} 

template <typename T>
T setStruct(T t) {   
    if (typeid(t) == typeid(hello)) {
        t.name = "John";
    } 
    else {
        t.age = 0;
    }
    return t; 
}

int main() { 
    //printHello<hello>("HELLO"); // ERROR: no member named t.age 
    hello h;
    h = setStruct(h); // ERROR: no member named t.age
    return 0;
}
pseudo
  • 385
  • 2
  • 19

3 Answers3

5

printHello won't ever be able to work, as you want to perform a compile-time branch on a run-time string value.

setStruct is closer to a possible solution but, again, typeid returns a run-time value - you need a compile-time branching predicate in order to conditionally compile either the .name or .age access.

In C++17, you can solve this issue easily with if constexpr and std::is_same_v:

template <typename T>
T setStruct(T t) {   
    if constexpr(std::is_same_v<T, hello>) {
        t.name = "John";
    } 
    else {
        t.age = 0;
    }
    return t; 
}

More information on "if constexpr vs if" here.


Note that your particular example can be simply solved by providing multiple overloads:

hello setStruct(hello t)
{
    t.name = "John";
    return t;
}

bye setStruct(bye t)
{
    t.age = 0;
    return t;
}
Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • What if I would like to get the value inside struct? Do the same overloading strategy works? – pseudo Apr 13 '17 at 21:12
  • @pseudo: yes - you should get familiar with overloading as it's at the core of the language. – Vittorio Romeo Apr 13 '17 at 21:14
  • @pseudo The solution brought up by Vittorio is an advanced, niche feature. Your `setStruct` function makes me think you should learn the basics first, like what a "constructor" is. Then overloading, inheritance, polymorphism, etc. – n.caillou Apr 13 '17 at 21:23
1

I am trying to set the fields inside struct dynamically using templates.

I think you are using the wrong strategy. You can use simple overloads and avoid the problems associated with function templates completely.

hello setStruct(hello h)
{
   h.name = "John";
   return h;
}

bye setStruct(bye b)
{
   b.age = 0;
   return b;
}

A function template is worthwhile only when majority of the code is type-independent.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

What you can do in C++11 is using type_traits and SFINAE.

Below, an example of how you can handle your problem:

#include <string>
#include <type_traits>

struct A {
  std::string name;
};

struct B {
  int age;
};

template<typename T>
typename std::enable_if<std::is_same<T, A>::value>::type
setStruct(T* t) {
  t->name = "This is a string";
}

template<typename T>
typename std::enable_if<std::is_same<T, B>::value>::type
setStruct(T* t) {
  t->age = 47;
}

int main(int argc, char *argv[]) {
  A a;
  B b;
  setStruct(&a);
  setStruct(&b);
  return 0;
}

IMHO, this design is a bad choice. It makes the code unreadable and can be easily avoided with other patterns: like polymorphic classes, overloading, or restructuring yours data structures.

BiagioF
  • 9,368
  • 2
  • 26
  • 50