简体   繁体   English

如何通过引用或指针将int和unsigned int成员传递给同一函数?

[英]How can I pass both `int` and `unsigned int` members, by reference or pointer, to the same function?

I have a 20-30 line C++ function which was taking a reference to an int for possible updation. 我有一个20-30行的C ++函数,该函数正在引用一个int以进行可能的更新。 Now I am replacing the member which was passed to it with a member of a member encapsulating more data, something like: 现在,我将封装了更多数据的成员替换为传递给它的成员,例如:

searchState.matchedOK = specificSearch(*pageIndices.GetStringIByRef(), searchState); //new, and overwritten.
searchState.matchedOK = specificSearch(pageOffsetInText, searchState); //old

I want to localise this modification to the lines and function called above because the old member should be removed once I have verified equivalence and beyond. 我想将此修改本地化为上面调用的行和函数,因为一旦我验证了等效性及以后的功能,就应删除旧成员。

Is this possible with simple casts? 简单的转换有可能吗?

If you want code: 如果您需要代码:

static bool specificSearch(int &matchLocation, const SearchSpecs &specs) {/**/}

and the recently added member: 和最近添加的成员:

inline unsigned int *GetStringIByRef() {return &stringI;}

I'm not 100% sure I understand your question, so I might completely miss the mark here. 我不确定100%理解您的问题,因此我可能会完全错过这里的记号。 But if you make your function a template: 但是,如果您将函数设为模板:

template<typename IntType>
static bool specificSearch(IntType &matchLocation, const SearchSpecs &specs) {/**/}

That will allow you to pass either type to it. 这样您就可以将任何一种类型传递给它。

Your basic problem is that your function specificSearch assigns to an int object. 您的基本问题是您的函数specificSearch分配给一个int对象。 But the thing you want written is an unsigned int object. 但是您要编写的东西是一个unsigned int对象。 Fortunately, the strict aliasing rules allows us to write to an unsigned int as if it were an int . 幸运的是,严格的别名规则使我们能够像写unsigned int一样写入unsigned int int The type system doesn't exactly encourage it, but can be persuaded: 类型系统并不完全鼓励它,但是可以被说服:

searchState.matchedOK = specificSearch(*reinterpret_cast<int*>(pageIndices.GetStringIByRef()), searchState);

This sort-of relies on the value being written to be in the common range of the two types (0 to INT_MAX ). 这种排序取决于要写入的值处于两种类型(0到INT_MAX )的公共范围内。 I say "sort of", because on 2's complement systems the result of writing a value outside that range is the same as the result of converting the value to unsigned int . 我之所以说“ sort of”,是因为在2的补码系统中,写入超出该范围的值的结果与将值转换为unsigned int的结果相同。 On non-2's-complement systems, which in practice don't exist but in principle plague our attempts at portable code, the result is different and hence probably wrong. 在实际上不存在但原则上困扰我们尝试可移植代码的非2's补码系统上,结果是不同的,因此可能是错误的。

It might be better if possible to define an overload of specificSearch : 如果可能的话,定义specificSearch的重载可能会更好:

static bool specificSearch(unsigned int &matchLocation, const SearchSpecs &specs) {
    int loc;
    bool retval = specificSearch(loc, specs);
    if (retval) { // I'm guessing here about the meaning of the return value
        matchLocation = loc; // converts int to unsigned int
    }
    return retval;
}

This assumes that the wrapper function can tell whether or not the "real" specificSearch assigned to loc or not, so that it knows whether or not to assign to matchLocation . 假设包装函数可以告诉“真正的” specificSearch分配给loc ,从而知道是否分配给matchLocation If the calling function can't somehow figure that out then this doesn't really work (and if specificSearch is permitted to assign and then throw an exception, you need to account for that too). 如果调用函数无法以某种方式弄清楚这一点,那么这实际上是行不通的(并且如果允许specificSearch分配然后抛出异常,那么您也需要考虑这一点)。

It would be more sensible if possible to change stringI to the right type. 如果可能的话,将stringI更改为正确的类型会更明智。

You can do this with templates: 您可以使用模板执行此操作:

template<typename T>
static bool specificSearch(T& matchLocation, const SearchSpecs& specs) {/**/}

And assign to matchLocation inside the function. 并在函数内部分配给matchLocation This way, you can use any type that can be assigned to whatever type it is you're assigning to matchLocation in the function. 这样,您可以使用可以分配给函数中的matchLocation任何类型。

If, for some reason, you don't like that, and you want it to only work with int and unsigned int , you can use template specialisation: 如果由于某种原因您不喜欢它,并且希望它仅与intunsigned int使用,则可以使用模板专门化:

// leaving this undefined, which will cause a linker error if you use it with other types
template<typename T>
static bool specificSearch(T& matchLocation, const SearchSpecs& specs);

template<>
static bool specificSearch<int>(int& matchLocation, const SearchSpecs& specs) {
    /* definition */
}

template<>
static bool specificSearch<unsigned int>(unsigned int& matchLocation, const SearchSpecs& specs) {
    // use the other one to avoid code duplication
    int tmp = matchLocation;
    bool retval = specificSearch(tmp, specs);
    matchLocation = tmp;
    return retval;
}

Note that you will probably get warnings for conversions between int and unsigned int using these functions, because the ranges of the two types are different. 注意,使用这两个函数可能会在intunsigned int之间进行转换时发出警告,因为两种类型的范围是不同的。

I see several issues here. 我在这里看到几个问题。 First of all, depending on your intentions it may be better to return merely stringI by value. 首先,根据您的意图,最好仅按值返回stringI Otherwise you could adjust its signature as follows: 否则,您可以如下调整其签名:

inline unsigned int &GetStringIByRef() { return stringI; }

in order to make use of C++ references. 为了利用C ++引用。

As for 至于

static bool specificSearch(int &matchLocation, const SearchSpecs &specs) {/**/}

you would call it then as follows: 您可以按如下调用它,则

searchState.matchedOK = specificSearch(reinterpret_cast<unsigned int&>(pageIndices.GetStringIByRef()), searchState);

Still depends on the object itself (in case it is const ), I reckon. 我认为仍然取决于对象本身(如果是const )。

If anything unclear or I missed the point, comment and I'll adjust my answer. 如果有任何不清楚的地方或我错过了要点,请发表评论,然后我将调整答案。

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

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