开发者

Can it cause problems to explicitly pass a reference into a function template that's not expecting one?

开发者 https://www.devze.com 2023-03-22 05:52 出处:网络
There was a question regarding passing taking the following function template, and instantiating it with a by-reference string parameter:

There was a question regarding passing taking the following function template, and instantiating it with a by-reference string parameter:

template <typename T>
void foo(T t) {}

The answer was, of course, to give the argument explicitly:

int main() {
   std::string str("some huge text");
   foo<std::string&>(str);
}

(As an aside, there was a suggestion about using deduction and passing C++0x's std::ref(str), but this requires the use of .get() inside the function, and the OP's requirement was transparency.)

Howev开发者_Python百科er, IMO there can be little doubt that the author of the function template intended for the argument to be passed by value, or he would have written:

template <typename T>
void foo(T& t) {}

(It's possible that he deliberately intended for either to be possible, but this seems unlikely to me for some reason.)

  • Are there any "reasonable" scenarios where passing a reference into foo<T>, where the author of foo had intended the function always to take its argument by value, may cause problems?

  • The answer I'm looking for most likely consists of a function body for foo, where the use of a reference type for T leads to unexpected/undesirable semantics when compared to the use of a value type for T.


Consider that it's common to write algorithms like this:

template <typename InputIterator>
void dosomething(InputIterator first, InputIterator last, otherparams) {
    while (first != last) {
        do the work;
        ++first;
    }
}

It's also how the standard algorithms are implemented both in GCC and in the old SGI STL.

If first is taken by reference then it will be modified, so certainly there are plenty of template functions out there that will "go wrong" with reference template arguments. In this example, first is changed to a value equal to last. In another implementation, or in the next release, it might be copied and not modified at all. That's "unexpected/undesirable semantics".

Whether you call this a "problem" or not, I'm not sure. It's not the behavior that the author of the function intended, and it's probably not documented what happens to first if it's passed by reference (it isn't for the standard algorithms).

For the standard algorithms I think it's UB, so the caller is at fault. The standard says that the template argument should be an iterator, and while T* or some library iterator is an iterator type, T* & or reference-to-library-iterator isn't.

As long as authors of template functions have documented the requirements of their template arguments clearly, I suspect that typically it will just fall out in the same way as for standard algorithms and iterators -- reference types are not valid template arguments, and hence the caller is at fault. In cases where the requirements are very simple (a couple of expressions with specified behavior), a reference type probably isn't ruled out, but again as long as the function doesn't say that it doesn't modify the argument, and doesn't say how it modifies the argument, callers should consider that since it's not documented how the argument is modified, then it's unspecified. If they call the function with a reference type, and get surprised whether or how the argument is modified, again it's the caller's fault.

I expect that under-documented functions are at risk of a dispute whose fault it is when it goes wrong, though, since sometimes it'll rely on quite a close reading.


If the programmer decided to be lazy, and use the input parameter as a temporary variable to calculate the output, then you would get problematic results:

template <class T>
T power2n(T a, int n) {
    if (n == 0) return 1;
    for (int i = 0 ; i < n; i++) 
    {
       a *= a; 
    }
    return a;
}

Now if I pass the first parameter by reference, its value gets messed up.

Not saying this is good programming, just saying it happens.

0

精彩评论

暂无评论...
验证码 换一张
取 消