【问题标题】:Dynamically set struct with template C++使用模板 C++ 动态设置结构
【发布时间】:2017-04-13 20:57:26
【问题描述】:

我正在尝试使用模板动态设置结构内的字段。我已经在代码中编写了这两种方法。两种方法都不起作用说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;
}

【问题讨论】:

标签: c++ templates dynamic struct


【解决方案1】:

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

【讨论】:

  • 如果我想获取 struct 中的值怎么办?相同的重载策略是否有效?
  • @pseudo:是的 - 你应该熟悉重载,因为它是语言的核心。
  • @pseudo Vittorio 提出的解决方案是一个先进的小众功能。你的setStruct 函数让我觉得你应该先学习基础知识,比如“构造函数”是什么。然后是重载、继承、多态等
【解决方案2】:

我正在尝试使用模板动态设置结构内的字段。

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

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

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

函数模板只有在大部分代码与类型无关时才有价值。

【讨论】:

    【解决方案3】:

    您可以在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;
    }
    

    恕我直言,这种设计是一个糟糕的选择。它使代码不可读,并且 可以通过其他模式轻松避免:例如 多态类重载或重组您的数据结构。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      • 1970-01-01
      • 2010-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多