使用模板C ++动态设置struct

时间:2017-04-13 20:57:26

标签: c++ templates dynamic struct

我正在尝试使用模板动态设置struct中的字段。我在代码中写了两种方法。两种方法都不起作用no member named t.age.我如何动态设置字段?任何帮助表示赞赏。

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

3 个答案:

答案 0 :(得分:5)

printHello无法工作,因为您希望在运行时字符串值上执行编译时分支。

setStruct更接近可能的解决方案但是,typeid再次返回运行时值 - 您需要编译时分支谓词才能有条件地编译.name.age访问。

在C ++ 17中,您可以使用if constexprstd::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; 
}

更多信息on "if constexpr vs if" here.

请注意,您可以通过提供多个重载来简单地解决您的特定示例:

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

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

答案 1 :(得分:1)

  

我正在尝试使用模板动态设置struct中的字段。

我认为你使用了错误的策略。您可以使用简单的重载并完全避免与函数模板相关的问题。

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

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

只有当大多数代码与类型无关时,才能使用函数模板。

答案 2 :(得分:1)

您可以在 C ++ 11 中使用type_traitsSFINAE

下面是一个如何处理问题的示例:

#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;
}
恕我直言,这个设计是一个糟糕的选择。它使代码不可读 可以使用其他模式轻松避免:例如多态类重载,或重构您的数据结构。