Why does the implicit type conversion not work in template deduction?
Clash Royale CLAN TAG#URR8PPP
up vote
10
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
10
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
3
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago
add a comment |
up vote
10
down vote
favorite
up vote
10
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 1 hour ago


YSC
18.5k34388
18.5k34388
asked 1 hour ago
Yulong Ao
441617
441617
3
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago
add a comment |
3
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago
3
3
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago
add a comment |
2 Answers
2
active
oldest
votes
up vote
10
down vote
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
1 hour ago
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
add a comment |
up vote
1
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.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
10
down vote
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
1 hour ago
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
add a comment |
up vote
10
down vote
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
1 hour ago
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
add a comment |
up vote
10
down vote
up vote
10
down vote
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 1 hour ago
answered 1 hour ago


YSC
18.5k34388
18.5k34388
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
1 hour ago
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
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
1 hour ago
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
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
1 hour ago
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
1 hour ago
1
1
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
@FrancisCugler This is true ... but ... If OP did X, according to X, all, some, or none of my solutions would break.
– YSC
1 hour ago
add a comment |
up vote
1
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.
add a comment |
up vote
1
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.
add a comment |
up vote
1
down vote
up vote
1
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 55 mins ago
Yakk - Adam Nevraumont
176k19179361
176k19179361
add a comment |
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
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
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
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
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
3
Possible duplicate of C++ implicit type conversion with template
– jwismar
1 hour ago