1

I have a defined a simple template class. In this class I define a structure (struct NodeData) which is used for nodes of a graph. For the first code I give bellow, there is no compilation error even if I do an error on purpose in the method test (I do g[nId].anything = "something" even if struct NodeData dont have a variable called anything).

To understand where is the problem, in the second code I give bellow I have put my structs definitions and typedefs outside of MyClass. I have put template<typename T1, typename T2> on top of the definition of struct NodeData because this struct need to store 2 variables of abstract type T1 and T2. I also removed the keyword typename from the typedefs, and I have put NodeData<int, int> instead of NodeData in the first typedef (even if I don't want to do that actually), otherways it will give some errors at this line like: expected a type, got 'NodeData'. When I compile, it gives the following expected error (which is totally normal actually): 'struct NodeData<int, int>' has no member named 'anything', while for the first code I didn't get this error !

What is the difference between this two codes ? How can I do for the second code to not be obliged to specify NodeData for the first typedef (because members var1 and var2 of struct NodeData are not necessarily of type int) ? Or how can I do for the first code to work correctly and detect the error that NodeData has no member named anything ?

First code:

#include <iostream>
#include <boost/graph/adjacency_list.hpp>

using namespace std;
using namespace boost;

template<typename T1, typename T2>
class MyClass
{
    public:
        MyClass();
        virtual ~MyClass();
        void test(T1 p, T2 s);

    protected:
        struct NodeData
        {
            T1 var1;
            T2 var2;
            int var3;
        };

        struct EdgeData
        {
            int var;
        };

        typedef adjacency_list<setS, setS, undirectedS, NodeData, EdgeData> Graph;
        typedef typename Graph::vertex_descriptor NodeDataID;
        typedef typename Graph::edge_descriptor EdgeDataID;
        typedef typename graph_traits<Graph>::vertex_iterator VertexIterator;

        Graph g;
};

template<typename T1, typename T2>
void MyClass<T1, T2>::test(T1 arg1, T2 arg2)
{
    NodeDataID nId = add_vertex(g);
    g[nId].anything = "but anything is not in struct NodeData !";
    g[nId].var1 = arg1;
    g[nId].var2 = arg2;
    g[nId].var3 = 55;
}

template<typename T1, typename T2>
MyClass<T1, T2>::MyClass()
{
    // ...
}

template<typename T1, typename T2>
MyClass<T1, T2>::~MyClass()
{
    // ...
}

Second code:

#include <iostream>
#include <boost/graph/adjacency_list.hpp>

using namespace std;
using namespace boost;

template<typename T1, typename T2>
struct NodeData
{
    T1 var1;
    T2 var2;
    int var3;
};

struct EdgeData
{
    int var;
};

typedef adjacency_list<setS, setS, undirectedS, NodeData<int, int>, EdgeData> Graph;
typedef Graph::vertex_descriptor NodeDataID;
typedef Graph::edge_descriptor EdgeDataID;
typedef graph_traits<Graph>::vertex_iterator VertexIterator;

template<typename T1, typename T2>
class MyClass
{
    public:
        MyClass();
        virtual ~MyClass();
        void test(T1 p, T2 s);

    protected:
        Graph g;
};

template<typename T1, typename T2>
void MyClass<T1, T2>::test(T1 arg1, T2 arg2)
{
    NodeDataID nId = add_vertex(g);
    g[nId].anything = "but anything is not in struct NodeData !";
    g[nId].var1 = arg1;
    g[nId].var2 = arg2;
    g[nId].var3 = 55;
}

template<typename T1, typename T2>
MyClass<T1, T2>::MyClass()
{
    // ...
}

template<typename T1, typename T2>
MyClass<T1, T2>::~MyClass()
{
    // ...
}
4

1 に答える 1

2

テンプレートのインスタンス化がない場合、コードは生成されないため、コンパイル エラーは発生しません。これが、通常、テンプレートのいくつかの可能性のあるインスタンスを作成し、それらを使用して愚かな間違いを犯していないことを確認するテスト コードを用意することが重要である理由です。

編集:私が言っていることが明確でない場合に備えて、コードの一部を使用した例を追加しました。

#include <iostream>

template<typename T1, typename T2>
class MyClass
{
public:
    void Test(T1 p, T2 s);

protected:
    struct NodeData
    {
        T1 var1;
        T2 var2;
        int var3;
    };

private:
    NodeData m_g;
};

template<typename T1, typename T2>
void MyClass<T1, T2>::Test(T1 arg1, T2 arg2)
{
    // error C2039: 'anything' is not a member of 'MyClass<T1,T2>::NodeData'
    m_g.anything = "but anything is not in struct NodeData !";
    m_g.var1 = arg1;
    m_g.var2 = arg2;
    m_g.var3 = 55;
}

int main() {
    // if you comment out the lines using it the template will never be compiled
    MyClass<int, double> test; // instantiation of template with T1 = int and T2 = double
    test.Test(42, 3.14); // calling Test function

    std::cin.get();
    return 0;
}
于 2012-01-24T20:49:31.007 に答える