简体   繁体   English

c ++:类的通用getter

[英]c++ : Universal getter for class

I kind of need help! 我需要帮助! I want to define a template method for my class to access its private fields. 我想为我的类定义一个模板方法来访问它的私有字段。 Here is my code: 这是我的代码:

#include <string>
#include <vector>
using namespace std;

class ex
{
public:
    ex(string pegah_,int amin_):pegah(pegah_),amin(amin_){}
    template<typename T>
    T get_field(){
        if(is_same<T,string>::value)
            return pegah;
        else if(is_same<T,int> ::value)
            return amin;
    }
private:
    string pegah;
    int amin;
};

int main(void)
{
    string i = "salam";
    int o=10;
    ex y(i,o);
    y.get_field<string>();
}

as you see I want to use just one function. 如你所见,我只想使用一个功能。 But I keep getting this error: 但我一直收到这个错误:

test.cpp: In instantiation of ‘T ex::get_field() [with T = std::basic_string<char>]’:
test.cpp:30:21:   required from here
test.cpp:15:8: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
 return amin;
        ^
In file included from /usr/include/c++/4.8/string:52:0,
                 from test.cpp:1:
/usr/include/c++/4.8/bits/basic_string.h:490:7: error:   initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
       basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());

can anyone help? 有人可以帮忙吗?

Instead you could lay your code out like this: 相反,您可以像这样放置代码:

template<typename T> T get_field();

// outside the class:
template<> inline int ex::get_field<int>() { return amin; }
template<> inline string ex::get_field<string>() { return pegah; }

As you have it now, all branches of the if..else must compile. 正如你现在所拥有的那样, if..else所有分支都必须编译。

Basically you have three options to do it. 基本上你有三种选择。

First using explicit specialization of template member function. 首先使用模板成员函数的显式特化。

class Foo {
public:
    template <typename T>
    T get () const;

private:
    std::string str {"XXX"};
    int value {42};
};


template <>
inline std::string Foo::get () const {
    return str;
}

template <>
inline int Foo::get () const {
    return value;
}

Second one is to use helper function with different parameters type. 第二个是使用具有不同参数类型的辅助函数。

class Foo2 {
public:
    template <typename T>
    T get () const {
        return get_helper (typename std::is_same<T, std::string>::type {});
    }


private:
    std::string get_helper (std::true_type) const {
        return str;
    }

    int get_helper (std::false_type) const {
        return value;
    }

private:
    std::string str {"YYY"};
    int value {44};
};

Third option is to use SFINAE. 第三种选择是使用SFINAE。

class Foo3 {
public:
    template <typename T>
    typename std::enable_if<std::is_same<T, std::string>::value, T>::type get () const {
        return str;
    }

    template <typename T>
    typename std::enable_if<std::is_same<T, int>::value, T>::type get () const {
        return value;
    }

private:
    std::string str {"ZZZ"};
    int value {45};
};

and usage would be like: 用法如下:

template <typename T>
void show (T v) {
    std::cout << v << std::endl;
}

Foo f1;
show (f1.get<std::string> ());
show (f1.get<int> ());

Foo2 f2;
show (f2.get<std::string> ());
show (f2.get<int> ());

Foo3 f3;
show (f3.get<std::string> ());
show (f3.get<int> ());

Second option is helpful when you want to distinguish between two types. 当您想要区分两种类型时,第二个选项很有用。 If you have more getters, then probably you will need to use first or third option. 如果你有更多的吸气剂,那么你可能需要使用第一个或第三个选项。

I think it is better you define a getter and setter for each field. 我认为最好为每个字段定义一个getter和setter。 That is a better approach. 这是一种更好的方法。 It's easier to read and to understand and you achieve the same as with the template technique. 它更容易阅读和理解,你实现与模板技术相同。


Explanation of your code: 您的代码说明:

It does not compile because of type checking. 由于类型检查,它无法编译。 Template functions are generated when used in C++11. 在C ++ 11中使用时会生成模板函数。 You use it with template parameter string so the function is generated. 您将它与模板参数string一起使用,以便生成该函数。 The problem is that you generate a function that returns T as a string , but you have code in your function that returns int (variable amin ). 问题是你生成一个函数,它返回T作为一个string ,但你的函数中有代码返回int (变量amin )。 Generate the function in your mind like so for T equals string : 如果T等于string ,则在脑海中生成函数:

string get_field(){
    if(is_same<string,string>::value)
        return pegah;                      // OK
    else if(is_same<string,int> ::value)
        return amin;                       // NOT OK, amin is of type int
}

One solution is that of MM , it's called specialization. 一种解决方案是MM ,它被称为专业化。 You specialize a template for (a) specific argument(s). 您专门为(a)特定参数设置模板。 And there are also other answers coming up. 还有其他答案即将出现。


I do not recommend that, because you finally do nothing else but generating getter functions for each variable in a specialized template. 我不建议这样做,因为除了为专用模板中的每个变量生成getter函数之外,你最后什么都不做。 You could as well just have written: 你也可以写一下:

string get_pegah(){ return pegah; }
int get_amin() { return amin; }

Easier to read, to maintain and straight forward. 更易于阅读,维护和直接。 And more efficient I think. 我觉得效率更高。


as you see I want to use just one function 如你所见,我只想使用一个功能

You don't really. 你真的不是。 You either call get_field<string> or get_field<int> and when called the appropriate function would be generated; 您可以调用get_field<string>get_field<int>并在调用时生成相应的函数; either with T=string , T=int or both (depending on your use case). 使用T=stringT=int或两者(取决于您的用例)。 Though as you have learned by now, it's an error to do so in that case. 虽然你现在已经学会了,但在这种情况下这样做是错误的。

What you probably meant was that you want to have one function definition to do what you want. 您可能意味着您希望有一个函数定义来执行您想要的操作。 I don't think that is possible. 我不认为这是可能的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM