关于c ++:类中的模板函数

Template function in class

我不知道该怎么办。我总是通过使用一个简单的类和一个简单的模板函数得到一个错误。我读了所有其他的解决方案,但它们没有帮助我。

除了一些其他类,我还有一些简单的类数据:

1
2
3
4
5
6
7
8
9
10
11
class Data{
public:
    template <class T>
    T dat();
    int id;
    union{
        char c;
    int i;
    double d;
    };
};

以及函数dat:

1
2
3
4
5
6
template <class T>
T Data::dat(){
    if(id == 1) return i;
    if(id == 2) return d;
    if(id == 3) return c;
}

如您所见,我想检查ID并返回int、double或char。现在我试着打印主函数中的值,如下所示:

1
2
3
4
Data test;
test.id=1;
test.i = 12;
cout<<test.dat();

但我总是收到这个错误消息:

1
Error: Could not find a match for Data::dat<Data::T>() needed in main(int, char**).

问题出在哪里??

谢谢你


要准确地说,您希望函数的返回类型取决于对象中的id字段;换句话说,动态地。模板是在编译时解析的,因此它们在这里无能为力。你必须归还boost::variantboost::any支持这种动态打字。


I don't know what to do. I always get an error by using a simple class and a simple template function. I read all the other solutions but they didn't helped me.

在我看来,你想建立一个有歧视的联盟。

因为模板函数的返回类型是在编译时确定的(即在ID中设置值并尝试调用函数之前),所以您的实现无法工作。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class Data
{
    enum value_type {
        int_val, char_val, double_val
    } discriminator; // private (the user doesn't see this)
                     // this replaces your id

    union{
        char c;
        int i;
        double d;
    } value;

public:
    class wrong_type_error: public std::logic_error
    {
    public:
        wrong_type_error(const std::string& msg): std::logic_error(msg) {}
    };

    explicit Data(const char c)
    : discriminator(Data::char_value)
    , value.c(c)
    {
    }

    explicit Data(const int i)
    : discriminator(Data::int_value)
    , value.i(i)
    {
    }

    explicit Data(const double d)
    : discriminator(Data::double_value)
    , value.d(d)
    {
    }

    // don't put this here: int id;

    // this part can be optimized to simpler (more idiomatic) code
    template<typename T> T get() const; // undefined
    template<> int get() const {
        if(discriminator != Data::int_val)
            throw wrong_type_error("Cannot return a int from Data instance");
        return value.i;
    }
    template<> char get() const {
        if(discriminator != Data::char_val)
            throw wrong_type_error("Cannot return a char from Data instance");
        return value.c;
    }
    template<> double get() const {
        if(discriminator != Data::double_val)
            throw wrong_type_error("Cannot return a double from Data instance");
        return value.d;
    }
};

客户端代码:

1
2
Data test(10.5);
cout<<test.get<double>();

尽管如此,根据您的需要,您应该考虑使用boost::variant或boost::any实例。


dat()没有涉及T的参数,因此编译器不能从调用中推断T,必须明确提供,例如:

1
cout << test.dat<int>();

另外,请记住,您必须在头文件中实现dat()


使用此:

1
cout<<test.dat<int>();


VS2012表示"错误C2783:'t data::dat(void)':无法推导't'的模板参数。"

您只需要告诉函数dat什么是T

1
cout<<test.dat<int>();

如果传递模板化参数,则可以推导模板类型,但不能猜测返回类型。