3
template<typename T>
void func(const T &x) {
    cout << "base template "<<x<<"\n";
}

template<>
void func(const int &x) {
    cout << "int specialization "<<x<<"\n";
}

template<>
void func(const double &x) {
    cout << "double specialization "<<x<<"\n";
}

int main() {
    int five = 5;
    func(five); // prints int specialization 5
    double d = 3.14;
    func<int>(d); // prints int specialization 3
}

Now with const removed

template<typename T>
void func( T &x) {
    cout << "base template "<<x<<"\n";
}

template<>
void func( int &x) {
    cout << "int specialization "<<x<<"\n";
}

template<>
void func( double &x) {
    cout << "double specialization "<<x<<"\n";
}

int main() {
    int five = 5;
    func(five); // prints int specialization 5
    double d = 3.14;
    func<int>(d); // throws compile error
}

Why do I get a compilation error in func<int>(d) where as in the const version everything compiled fine ?

Error C2664 'void func(int &)': cannot convert argument 1 from 'double' to 'int &'

I came across this when I was trying out some examples on my own for template specialization.

I'm looking for reading links and posts that might be helpful.

4
  • 4
    Removing the const allows to modify x, and this is a problem because the d that you pass as an argument is not actually an int (but a double). Using const allows to bind to a temporary that is the result of converting yout double d to int.
    – wohlstad
    Commented Aug 4, 2023 at 12:40
  • 4
    Early in the morning, and I haven't checked, but I suspect that templates are a distraction here. Try a single function void func(int&) and call it with func(d); . Commented Aug 4, 2023 at 12:56
  • please include the compiler error in the question. I holds valuabe information Commented Aug 4, 2023 at 13:38
  • You could provide an explicit temporary to work around the language constraint. template <typename T> struct temp { T var; temp(T value) : var{value} {} operator T&() { return var; } }; and then call the function by func<int>(temp<int>(d));. Don't do this in real code; shown here for educational purposes.
    – Eljay
    Commented Aug 4, 2023 at 15:37

1 Answer 1

10

The issue is not actually related to templates:

Your double d needs to be converted to an int in order to be an argument for a function expecting an int reference.

But since the converted int is a temporary (i.e. a R-value) it cannot be bound to an int &, but only to a const int &.

You can observe this without any template:

void func1(const int& x) 
{
}

void func2(int& x) 
{
}

int main() 
{
    double d = 3.14;
    func1(d);   // This compiles.
    func2(d);   // This does not. Error on MSVC: cannot convert argument 1 from 'double' to 'int &'
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.