Why does the implicit type conversion not work in template deduction?
up vote
12
down vote
favorite
In the following code, I want to call a template function by implicitly converting an int
to a Scalar<int>
object.
#include<iostream>
using namespace std;
template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;
Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.
test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);
c++ c++11 templates
add a comment |
up vote
12
down vote
favorite
In the following code, I want to call a template function by implicitly converting an int
to a Scalar<int>
object.
#include<iostream>
using namespace std;
template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;
Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.
test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);
c++ c++11 templates
4
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38
add a comment |
up vote
12
down vote
favorite
up vote
12
down vote
favorite
In the following code, I want to call a template function by implicitly converting an int
to a Scalar<int>
object.
#include<iostream>
using namespace std;
template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;
Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.
test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);
c++ c++11 templates
In the following code, I want to call a template function by implicitly converting an int
to a Scalar<int>
object.
#include<iostream>
using namespace std;
template<typename Dtype>
class Scalar
public:
Scalar(Dtype v) : value_(v)
private:
Dtype value_;
;
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
int main()
int a = 1;
func(a, 2);
//int b = 2;
//func(a, b);
return 0;
Why does the template argument deduction/substitution fail? And the commented-codes are also wrong.
test.cpp: In function ‘int main()’:
test.cpp:19:12: error: no matching function for call to ‘func(int&, int)’
func(a, 2);
^
test.cpp:19:12: note: candidate is:
test.cpp:13:6: note: template<class Dtype> void func(int, Scalar<Dtype>)
void func(int a, Scalar<Dtype> b){
^
test.cpp:13:6: note: template argument deduction/substitution failed:
test.cpp:19:12: note: mismatched types ‘Scalar<Dtype>’ and ‘int’
func(a, 2);
c++ c++11 templates
c++ c++11 templates
edited Nov 9 at 14:46
YSC
19.2k34590
19.2k34590
asked Nov 9 at 14:33
Yulong Ao
453617
453617
4
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38
add a comment |
4
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38
4
4
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38
add a comment |
2 Answers
2
active
oldest
votes
up vote
13
down vote
accepted
Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int
-> Scalar<int>
is a user-defined conversion.
If you want to use TAD, you need to convert your argument at the caller site:
func(a, Scalar<int>2);
or define a deduction guide1 for Scalar
and call f
:
func(a, Scalar2); // C++17 only
Alternatively, you can explicitly instantiate f
:
func<int>(a, 2);
1) The default deduction guide is sufficient: demo.
I've tested all three of your solutions and they will work as is; however if the OP declaredScalar()
asexplicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
– Francis Cugler
Nov 9 at 14:47
add a comment |
up vote
2
down vote
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));
template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.
Conversion is done later, at overload resolution & function call time.
Here, we add another overload that explicitly forwards to the one you want.
You probably wantb
to be aDtype&&
and usestd::forward
instead ofstd::move
for perfect forwarding.
– isanae
Nov 9 at 17:17
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
13
down vote
accepted
Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int
-> Scalar<int>
is a user-defined conversion.
If you want to use TAD, you need to convert your argument at the caller site:
func(a, Scalar<int>2);
or define a deduction guide1 for Scalar
and call f
:
func(a, Scalar2); // C++17 only
Alternatively, you can explicitly instantiate f
:
func<int>(a, 2);
1) The default deduction guide is sufficient: demo.
I've tested all three of your solutions and they will work as is; however if the OP declaredScalar()
asexplicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
– Francis Cugler
Nov 9 at 14:47
add a comment |
up vote
13
down vote
accepted
Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int
-> Scalar<int>
is a user-defined conversion.
If you want to use TAD, you need to convert your argument at the caller site:
func(a, Scalar<int>2);
or define a deduction guide1 for Scalar
and call f
:
func(a, Scalar2); // C++17 only
Alternatively, you can explicitly instantiate f
:
func<int>(a, 2);
1) The default deduction guide is sufficient: demo.
I've tested all three of your solutions and they will work as is; however if the OP declaredScalar()
asexplicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
– Francis Cugler
Nov 9 at 14:47
add a comment |
up vote
13
down vote
accepted
up vote
13
down vote
accepted
Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int
-> Scalar<int>
is a user-defined conversion.
If you want to use TAD, you need to convert your argument at the caller site:
func(a, Scalar<int>2);
or define a deduction guide1 for Scalar
and call f
:
func(a, Scalar2); // C++17 only
Alternatively, you can explicitly instantiate f
:
func<int>(a, 2);
1) The default deduction guide is sufficient: demo.
Because template argument deduction is not that smart: it does not (by design) consider user-defined conversions. And int
-> Scalar<int>
is a user-defined conversion.
If you want to use TAD, you need to convert your argument at the caller site:
func(a, Scalar<int>2);
or define a deduction guide1 for Scalar
and call f
:
func(a, Scalar2); // C++17 only
Alternatively, you can explicitly instantiate f
:
func<int>(a, 2);
1) The default deduction guide is sufficient: demo.
edited Nov 9 at 14:54
answered Nov 9 at 14:38
YSC
19.2k34590
19.2k34590
I've tested all three of your solutions and they will work as is; however if the OP declaredScalar()
asexplicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
– Francis Cugler
Nov 9 at 14:47
add a comment |
I've tested all three of your solutions and they will work as is; however if the OP declaredScalar()
asexplicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.
– Francis Cugler
Nov 9 at 14:47
I've tested all three of your solutions and they will work as is; however if the OP declared
Scalar()
as explicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.– Francis Cugler
Nov 9 at 14:47
I've tested all three of your solutions and they will work as is; however if the OP declared
Scalar()
as explicit
the third one will not compile. Not sure if this is something worth mentioning or not, but might be something important for the OP to be aware of.– Francis Cugler
Nov 9 at 14:47
add a comment |
up vote
2
down vote
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));
template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.
Conversion is done later, at overload resolution & function call time.
Here, we add another overload that explicitly forwards to the one you want.
You probably wantb
to be aDtype&&
and usestd::forward
instead ofstd::move
for perfect forwarding.
– isanae
Nov 9 at 17:17
add a comment |
up vote
2
down vote
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));
template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.
Conversion is done later, at overload resolution & function call time.
Here, we add another overload that explicitly forwards to the one you want.
You probably wantb
to be aDtype&&
and usestd::forward
instead ofstd::move
for perfect forwarding.
– isanae
Nov 9 at 17:17
add a comment |
up vote
2
down vote
up vote
2
down vote
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));
template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.
Conversion is done later, at overload resolution & function call time.
Here, we add another overload that explicitly forwards to the one you want.
template<typename Dtype>
void func(int a, Scalar<Dtype> b)
cout << "ok" <<endl;
template<typename Dtype>
void func(int a, Dtype b)
func(a, Scalar<Dtype>(std::move(b)));
template argument deduction is pattern matching, and it only matches the types or their base types exactly. It does no conversion.
Conversion is done later, at overload resolution & function call time.
Here, we add another overload that explicitly forwards to the one you want.
answered Nov 9 at 15:21
Yakk - Adam Nevraumont
177k19182362
177k19182362
You probably wantb
to be aDtype&&
and usestd::forward
instead ofstd::move
for perfect forwarding.
– isanae
Nov 9 at 17:17
add a comment |
You probably wantb
to be aDtype&&
and usestd::forward
instead ofstd::move
for perfect forwarding.
– isanae
Nov 9 at 17:17
You probably want
b
to be a Dtype&&
and use std::forward
instead of std::move
for perfect forwarding.– isanae
Nov 9 at 17:17
You probably want
b
to be a Dtype&&
and use std::forward
instead of std::move
for perfect forwarding.– isanae
Nov 9 at 17:17
add a comment |
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53227713%2fwhy-does-the-implicit-type-conversion-not-work-in-template-deduction%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
Possible duplicate of C++ implicit type conversion with template
– jwismar
Nov 9 at 14:38