How to implicitly convert class template object when passing as argument to function template?
Considering the following small code snippet:
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};
template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}
When trying to compile, I get the error
template argument deduction/substitution failed: [...] ‘A<int>’ is not derived from ‘const std::vector<T>’
While, on the other hand, if myFunc
is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc
accepts multiple vector types as argument, the compiler does not know to what type it should convert foo
to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A
to myFunc
?
c++ class templates casting implicit-conversion
add a comment |
Considering the following small code snippet:
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};
template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}
When trying to compile, I get the error
template argument deduction/substitution failed: [...] ‘A<int>’ is not derived from ‘const std::vector<T>’
While, on the other hand, if myFunc
is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc
accepts multiple vector types as argument, the compiler does not know to what type it should convert foo
to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A
to myFunc
?
c++ class templates casting implicit-conversion
2
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
3
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear howmyFunc
andA
are related.
– user463035818
Nov 21 '18 at 17:31
@NathanOliver IfmyFunc
is untemplated and takes, for instance, anstd::vector<float>
as argument,foo
is cast implicitely. Shouldn't the default value formyFunc
template (float
) be used then?
– joaocandre
Nov 21 '18 at 17:37
@user463035818 I've added a smallmain()
to reproduce the error.A
andmyFunc
aren't related.
– joaocandre
Nov 21 '18 at 17:38
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it asoperator std::vector<T>()
and you will still get the same error. You can make the entire classA
non-template either andbut makes no difference, still the same error.
– n.m.
Nov 21 '18 at 18:09
add a comment |
Considering the following small code snippet:
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};
template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}
When trying to compile, I get the error
template argument deduction/substitution failed: [...] ‘A<int>’ is not derived from ‘const std::vector<T>’
While, on the other hand, if myFunc
is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc
accepts multiple vector types as argument, the compiler does not know to what type it should convert foo
to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A
to myFunc
?
c++ class templates casting implicit-conversion
Considering the following small code snippet:
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>(){ /* implicit/explicit cast to std::vector */ }
};
template <typename T = float>
void myFunc(const std::vector<T>& _arg){
printf("myFuncn");
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
}
When trying to compile, I get the error
template argument deduction/substitution failed: [...] ‘A<int>’ is not derived from ‘const std::vector<T>’
While, on the other hand, if myFunc
is not a template, it will compile and run just fine. I assume the error is caused by the fact that since myFunc
accepts multiple vector types as argument, the compiler does not know to what type it should convert foo
to. However, shouldn't the default template values be used as fallback in such case? Is there an alternative way to be able to pass an object of class A
to myFunc
?
c++ class templates casting implicit-conversion
c++ class templates casting implicit-conversion
edited Nov 21 '18 at 17:48
YSC
25.5k557112
25.5k557112
asked Nov 21 '18 at 17:28
joaocandrejoaocandre
5051124
5051124
2
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
3
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear howmyFunc
andA
are related.
– user463035818
Nov 21 '18 at 17:31
@NathanOliver IfmyFunc
is untemplated and takes, for instance, anstd::vector<float>
as argument,foo
is cast implicitely. Shouldn't the default value formyFunc
template (float
) be used then?
– joaocandre
Nov 21 '18 at 17:37
@user463035818 I've added a smallmain()
to reproduce the error.A
andmyFunc
aren't related.
– joaocandre
Nov 21 '18 at 17:38
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it asoperator std::vector<T>()
and you will still get the same error. You can make the entire classA
non-template either andbut makes no difference, still the same error.
– n.m.
Nov 21 '18 at 18:09
add a comment |
2
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
3
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear howmyFunc
andA
are related.
– user463035818
Nov 21 '18 at 17:31
@NathanOliver IfmyFunc
is untemplated and takes, for instance, anstd::vector<float>
as argument,foo
is cast implicitely. Shouldn't the default value formyFunc
template (float
) be used then?
– joaocandre
Nov 21 '18 at 17:37
@user463035818 I've added a smallmain()
to reproduce the error.A
andmyFunc
aren't related.
– joaocandre
Nov 21 '18 at 17:38
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it asoperator std::vector<T>()
and you will still get the same error. You can make the entire classA
non-template either andbut makes no difference, still the same error.
– n.m.
Nov 21 '18 at 18:09
2
2
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
3
3
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how
myFunc
and A
are related.– user463035818
Nov 21 '18 at 17:31
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how
myFunc
and A
are related.– user463035818
Nov 21 '18 at 17:31
@NathanOliver If
myFunc
is untemplated and takes, for instance, an std::vector<float>
as argument, foo
is cast implicitely. Shouldn't the default value for myFunc
template (float
) be used then?– joaocandre
Nov 21 '18 at 17:37
@NathanOliver If
myFunc
is untemplated and takes, for instance, an std::vector<float>
as argument, foo
is cast implicitely. Shouldn't the default value for myFunc
template (float
) be used then?– joaocandre
Nov 21 '18 at 17:37
@user463035818 I've added a small
main()
to reproduce the error. A
and myFunc
aren't related.– joaocandre
Nov 21 '18 at 17:38
@user463035818 I've added a small
main()
to reproduce the error. A
and myFunc
aren't related.– joaocandre
Nov 21 '18 at 17:38
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as
operator std::vector<T>()
and you will still get the same error. You can make the entire class A
non-template either andbut makes no difference, still the same error.– n.m.
Nov 21 '18 at 18:09
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as
operator std::vector<T>()
and you will still get the same error. You can make the entire class A
non-template either andbut makes no difference, still the same error.– n.m.
Nov 21 '18 at 18:09
add a comment |
3 Answers
3
active
oldest
votes
Implicit conversions are not considered when attempting to deduce template parameters. Since A<int>
cannot match const std::vector<T>
, the myFunc
template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).
For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.
add a comment |
The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo)
the compiler is unable to determine a type for T. And that's really the end of the story.
See Template argument deduction on C++ reference.
Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.
See "C++ Function Templates: How Do They Really Work?" on youtube.
add a comment |
As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc
and do an explicit cast. Consider the following code:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Output of the program is:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
When you pass foo
to myFunc
the compiler uses the second overload of myFunc
which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo
to a std::vector
, hence doing the conversion before passing the resulting std::vector
to the first overload of myFunc
. Notice that:
you need a
const
conversion operator if you wnat to keep constness in the overloads ofmyFunc
.you need an additional template parameter pack
typename... Args
in the first overload ofmyFunc
to capture every specialization ofstd::vector
(say, with a custom allocator).
Another option could be to declare A
as class derived from std::vector
. Something like the following code:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
return 0;
}
In this case you do not need a conversion and you call myFunc
by slicing. A drawback to this approach is that you do the conversion to a std::vector
in the constructor and, every time you modify A
, you must keep the data of the base class std::vector
up to date.
add a comment |
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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%2f53417606%2fhow-to-implicitly-convert-class-template-object-when-passing-as-argument-to-func%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Implicit conversions are not considered when attempting to deduce template parameters. Since A<int>
cannot match const std::vector<T>
, the myFunc
template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).
For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.
add a comment |
Implicit conversions are not considered when attempting to deduce template parameters. Since A<int>
cannot match const std::vector<T>
, the myFunc
template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).
For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.
add a comment |
Implicit conversions are not considered when attempting to deduce template parameters. Since A<int>
cannot match const std::vector<T>
, the myFunc
template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).
For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.
Implicit conversions are not considered when attempting to deduce template parameters. Since A<int>
cannot match const std::vector<T>
, the myFunc
template is not a viable candidate. This remains true even if you explicitly instantiate it beforehand (and even if the conversion operator is not templated).
For overload resolution, implicit conversion are considered, which is why the non-templated version works. The templated version never gets to participate because it is not a viable candidate.
answered Nov 21 '18 at 18:03
Max LanghofMax Langhof
11.9k22241
11.9k22241
add a comment |
add a comment |
The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo)
the compiler is unable to determine a type for T. And that's really the end of the story.
See Template argument deduction on C++ reference.
Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.
See "C++ Function Templates: How Do They Really Work?" on youtube.
add a comment |
The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo)
the compiler is unable to determine a type for T. And that's really the end of the story.
See Template argument deduction on C++ reference.
Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.
See "C++ Function Templates: How Do They Really Work?" on youtube.
add a comment |
The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo)
the compiler is unable to determine a type for T. And that's really the end of the story.
See Template argument deduction on C++ reference.
Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.
See "C++ Function Templates: How Do They Really Work?" on youtube.
The problem is that template argument deduction does not consider implicit conversions, so when you write myFunc(foo)
the compiler is unable to determine a type for T. And that's really the end of the story.
See Template argument deduction on C++ reference.
Walter E. Brown gave a fantastic talk about how function templates work (including why you should call them function templates and not templatized functions) at CppCon2018 which I highly recommend.
See "C++ Function Templates: How Do They Really Work?" on youtube.
answered Nov 21 '18 at 18:04
Peter RudermanPeter Ruderman
10.2k2352
10.2k2352
add a comment |
add a comment |
As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc
and do an explicit cast. Consider the following code:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Output of the program is:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
When you pass foo
to myFunc
the compiler uses the second overload of myFunc
which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo
to a std::vector
, hence doing the conversion before passing the resulting std::vector
to the first overload of myFunc
. Notice that:
you need a
const
conversion operator if you wnat to keep constness in the overloads ofmyFunc
.you need an additional template parameter pack
typename... Args
in the first overload ofmyFunc
to capture every specialization ofstd::vector
(say, with a custom allocator).
Another option could be to declare A
as class derived from std::vector
. Something like the following code:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
return 0;
}
In this case you do not need a conversion and you call myFunc
by slicing. A drawback to this approach is that you do the conversion to a std::vector
in the constructor and, every time you modify A
, you must keep the data of the base class std::vector
up to date.
add a comment |
As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc
and do an explicit cast. Consider the following code:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Output of the program is:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
When you pass foo
to myFunc
the compiler uses the second overload of myFunc
which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo
to a std::vector
, hence doing the conversion before passing the resulting std::vector
to the first overload of myFunc
. Notice that:
you need a
const
conversion operator if you wnat to keep constness in the overloads ofmyFunc
.you need an additional template parameter pack
typename... Args
in the first overload ofmyFunc
to capture every specialization ofstd::vector
(say, with a custom allocator).
Another option could be to declare A
as class derived from std::vector
. Something like the following code:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
return 0;
}
In this case you do not need a conversion and you call myFunc
by slicing. A drawback to this approach is that you do the conversion to a std::vector
in the constructor and, every time you modify A
, you must keep the data of the base class std::vector
up to date.
add a comment |
As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc
and do an explicit cast. Consider the following code:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Output of the program is:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
When you pass foo
to myFunc
the compiler uses the second overload of myFunc
which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo
to a std::vector
, hence doing the conversion before passing the resulting std::vector
to the first overload of myFunc
. Notice that:
you need a
const
conversion operator if you wnat to keep constness in the overloads ofmyFunc
.you need an additional template parameter pack
typename... Args
in the first overload ofmyFunc
to capture every specialization ofstd::vector
(say, with a custom allocator).
Another option could be to declare A
as class derived from std::vector
. Something like the following code:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
return 0;
}
In this case you do not need a conversion and you call myFunc
by slicing. A drawback to this approach is that you do the conversion to a std::vector
in the constructor and, every time you modify A
, you must keep the data of the base class std::vector
up to date.
As noted in other answers, template resolution cannot consider implicit conversions. A simple way to solve the problem is to overload myFunc
and do an explicit cast. Consider the following code:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Output of the program is:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
When you pass foo
to myFunc
the compiler uses the second overload of myFunc
which, through an explicit cast, calls the conversion operator. In the second case we directly assign foo
to a std::vector
, hence doing the conversion before passing the resulting std::vector
to the first overload of myFunc
. Notice that:
you need a
const
conversion operator if you wnat to keep constness in the overloads ofmyFunc
.you need an additional template parameter pack
typename... Args
in the first overload ofmyFunc
to capture every specialization ofstd::vector
(say, with a custom allocator).
Another option could be to declare A
as class derived from std::vector
. Something like the following code:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv) {
A<int> foo;
myFunc(foo);
return 0;
}
In this case you do not need a conversion and you call myFunc
by slicing. A drawback to this approach is that you do the conversion to a std::vector
in the constructor and, every time you modify A
, you must keep the data of the base class std::vector
up to date.
answered Nov 22 '18 at 9:21
francescofrancesco
9241214
9241214
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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%2f53417606%2fhow-to-implicitly-convert-class-template-object-when-passing-as-argument-to-func%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
2
No implicit conversion will happen with a template function. You have to manually cast, if you want it converted to something it is not.
– NathanOliver
Nov 21 '18 at 17:30
3
please provide the code that causes the error (see also Minimal, Complete, and Verifiable example). Its not clear how
myFunc
andA
are related.– user463035818
Nov 21 '18 at 17:31
@NathanOliver If
myFunc
is untemplated and takes, for instance, anstd::vector<float>
as argument,foo
is cast implicitely. Shouldn't the default value formyFunc
template (float
) be used then?– joaocandre
Nov 21 '18 at 17:37
@user463035818 I've added a small
main()
to reproduce the error.A
andmyFunc
aren't related.– joaocandre
Nov 21 '18 at 17:38
The default argument is irrelevant because the entire conversion template is a red herring. You can declare it as
operator std::vector<T>()
and you will still get the same error. You can make the entire classA
non-template either andbut makes no difference, still the same error.– n.m.
Nov 21 '18 at 18:09