looking for some solutions? You are welcome.

SOLVED: Deducing a const l-value reference from a non-const l-value reference in C++ template

Paul Merrill:

Suppose you have the following pair of functions:

void f(const int&) { 
    // Do something, making a copy of the argument.
}

void f(int&&) { 
    // Do the same thing, but moving the argument.
}

They are fairly redundant—the only difference between the functions being whether they copy or move their argument. Of course, we can do better by re-writing this as a single template function:

template<typename T> 
void g(T&&) { 
    // Do something, possibly using std::forward to copy or move the argument.
}

This works, and is a commonly used idiom in practice. But the template might be instantiated into three functions, up from our two above. We can verify this occurs with the following piece of code:

#include <iostream>

template<typename T> constexpr char *type = nullptr;
template<> constexpr const char *type<int&> = "int&";
template<> constexpr const char *type<const int&> = "const int&";
template<> constexpr const char *type<int> = "int";

template<typename T> 
void g(T&&) { 
    std::cout << reinterpret_cast<void*>(&g<T>)
              << " = &g<" << type<T> << ">" << std::endl;
}

int main() {
    int i = 0;
    const int& cr = 0;

    g(i);
    g(cr);
    g(0);

    return 0;
}

/*
Prints:

0x100f45080 = &g<int&>
0x100f45100 = &g<const int&>
0x100f45180 = &g<int>
*/

This has added a third function for the case when T = int&, which we didn't have when we were using our non-templated function f above. In this case, we don't actually need this non-const l-value reference version of the function—given f was sufficient for our original needs—and this increases the size of our code, especially if we have many template functions written this way that call each other.

Is there a way to write our function g above so that the compiler will automatically deduce T = const int& when g(i) is called in our example code? I.e., a way where we don't have to manually write g<const int&>(i) yet still get the desired behavior.



Posted in S.E.F
via StackOverflow & StackExchange Atomic Web Robots
Share:

No comments:

Recent