【问题标题】:C++ template : A template to call variables by nameC++ 模板:按名称调用变量的模板
【发布时间】:2012-09-24 04:12:07
【问题描述】:

这个问题是之前一个问题的延续:How to template'ize variable NAMES, not types?

假设有以下代码:

struct VAR_TYPE{
public:
    bool is_fixed; 
    double value;      // Numerical value
    std::string name;  // Description of variable (to identify it by name)
    int reference_counter;
    /* ect. */
};

struct NODE{
public:
    VAR_TYPE X, Y, Z;
    /* ect. */
};

class MyClass{
public:
    std::vector <NODE_ptr> node;  // shared ptr, using boost::shared_ptr

    // what I have now
    void set_variable_X(int &i, double &P) { node[i]->X.value = P; }
    void set_variable_Y(int &i, double &P) { node[i]->Y.value = P; } 
    void set_variable_Z(int &i, double &P) { node[i]->Z.value = P; }

    // What I want to replace all 3 members with:
    <class T, class N>
    void set_variable( int &i, double &P, /* ??? */ ) { /* ??? */ }
    /* ect. */
};

我不确定在“???”的区域会发生什么是写的。借用上述链接中使用的伪代码,我想对

main(){
    MyClass S;
    double x1, y1, z1;
    int index; 

    // set x1, y1, z1, index

    S.set_variable( index, x1, &MyClass::node::X ); // in essence, what I want
    S.set_variable( index, y1, &MyClass::node::Y );
    S.set_variable( index, z1, &MyClass::node::Z );
};

我尝试了一些想法,但错误总是一团糟。我认为问题在于我使用的是 boost 共享指针和/或 std::vector。任何人都知道问题和合适的解决方案是什么?我一直在使用的一个选项是(但它不使用我在上面的 int main() 中确定的调用约定):

template < class T, class N >
void MyClass::set_reference( int &i, double &P,  
                         T NODE::* MemPtr,
                         N VAR_TYPE::* ValPtr)
{
    *MemPtr[i].*ValPtr.value = P; // doesn't work work
};

【问题讨论】:

    标签: c++ templates boost shared-ptr


    【解决方案1】:

    以下内容可以满足您的要求:

    #include <string>
    #include <vector>
    struct VAR_TYPE{
    public:
        bool is_fixed; 
        double value;      // Numerical value
        std::string name;  // Description of variable (to identify it by name)
        int reference_counter;
        /* ect. */
    };
    
    struct NODE{
    public:
        VAR_TYPE X, Y, Z;
        /* ect. */
    };
    
    class MyClass{
    public:
        std::vector <NODE *> node;  // shared ptr, using boost::shared_ptr
    
        // what I have now
        void set_variable_X(int &i, double &P) { node[i]->X.value = P; }
        void set_variable_Y(int &i, double &P) { node[i]->Y.value = P; } 
        void set_variable_Z(int &i, double &P) { node[i]->Z.value = P; }
    
        // What I want to replace all 3 members with:
        void set_variable( int &i, double &P, VAR_TYPE NODE::* ptr ) { (node[i]->*ptr).value = P;}
        /* ect. */
    };
    
    
    main(){
        MyClass S;
        double x1, y1, z1;
        int index; 
    
        // set x1, y1, z1, index
    
        S.set_variable( index, x1, &NODE::X ); // in essence, what I want
        S.set_variable( index, y1, &NODE::Y );
        S.set_variable( index, z1, &NODE::Z );
    }
    

    虽然我不明白“按名称调用变量的模板”是什么意思。顺便说一句,没有任何理由通过引用传递 i 和 P,你不应该这样做。

    【讨论】:

    • 非常好。一旦我获得足够的代表,我将为此 +1。如果node 被声明为std::vector&lt;NODE_ptr&gt; node(typedef boost::shared_ptr &lt;NODE&gt; NODE_ptr),有没有办法让它工作?我注意到您对i 和P 的评论。
    • 在std::vector&lt;NODE_ptr&gt; node 的情况下无需修改即可工作。我刚刚切换到原始指针,以免引入任何外部依赖,以防有人尝试编译。
    • 当 node 被声明为共享指针时,我无法编译它。我正在使用 gcc 4.5.2。我得到的错误是error: no match for ‘operator-&gt;*’ in ...。不过,如果节点被声明为std::vector &lt;NODE *&gt; node,我可以编译它。
    • 嗯,似乎 boost 人们忘了重载 ->* 运算符 :) 修复很简单,使用 ((*node[i]).*ptr).value = P; 代替,这样,你使用 shared_ptr 只是为了间接(* ) 并且在实际的 NODE &amp; 上调用 .* 操作
    • 在您看来,您认为 ->* 运算符被排除在外有正当理由吗?您提供的解决方案有效,因此我将其标记为答案。我欠你一杯啤酒。
    猜你喜欢
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 2012-08-29
    • 1970-01-01
    • 2011-09-01
    • 2017-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多