How to use derived type in specialisation of return-type function template? (“couldn't infer template...
I have a template class and a function with a template return type:
template<typename T>
class Wrapper {
public:
Wrapper(const T& _data) : data(_data) { }
const T& get_data() {return data;};
private:
T data;
};
template <typename T>
Wrapper<T> build_wrapped(){
T t{};
return Wrapper<T>(t);
}
Suppose that I want to extend the returned Wrapper
for one specific type T
and specialise the build_wrapped()
function for the type. So, let's create a template to hold the return type and use it in build_wrapped()
:
template<typename T>
struct ReturnType {
using type = Wrapper<T>;
};
template <typename T>
typename ReturnType<T>::type build_wrapped(){
T t{};
return typename ReturnType<T>::type(t);
}
And use it to provide the specialization:
struct Foo{};
class ExtendedWrapper : public Wrapper<Foo> {
public:
ExtendedWrapper(const Foo& _data) : Wrapper(_data) {}
int get_answer() {return 42;};
};
template<>
struct ReturnType<Foo> {
using type = ExtendedWrapper;
};
template<>
typename ReturnType<Foo>::type build_wrapped(){
Foo t{};
return typename ReturnType<Foo>::type(t);
}
However, the final declaration is rejected by both gcc and clang. For example, clang returns:
error: no function template matches function template specialization
'build_wrapped'
note: candidate template ignored: couldn't infer template argument 'T'
I can get around using ReturnType
by creating an explicit specialisation of Wrapper
for Foo
. However, this requires duplicating all the code in Wrapper
(in my real life case it's a substantial class), when I just want to add some new functionality (as in ExtendedWrapper
). So, can this be done? What's wrong with the approach above?
c++ templates template-specialization specialization
add a comment |
I have a template class and a function with a template return type:
template<typename T>
class Wrapper {
public:
Wrapper(const T& _data) : data(_data) { }
const T& get_data() {return data;};
private:
T data;
};
template <typename T>
Wrapper<T> build_wrapped(){
T t{};
return Wrapper<T>(t);
}
Suppose that I want to extend the returned Wrapper
for one specific type T
and specialise the build_wrapped()
function for the type. So, let's create a template to hold the return type and use it in build_wrapped()
:
template<typename T>
struct ReturnType {
using type = Wrapper<T>;
};
template <typename T>
typename ReturnType<T>::type build_wrapped(){
T t{};
return typename ReturnType<T>::type(t);
}
And use it to provide the specialization:
struct Foo{};
class ExtendedWrapper : public Wrapper<Foo> {
public:
ExtendedWrapper(const Foo& _data) : Wrapper(_data) {}
int get_answer() {return 42;};
};
template<>
struct ReturnType<Foo> {
using type = ExtendedWrapper;
};
template<>
typename ReturnType<Foo>::type build_wrapped(){
Foo t{};
return typename ReturnType<Foo>::type(t);
}
However, the final declaration is rejected by both gcc and clang. For example, clang returns:
error: no function template matches function template specialization
'build_wrapped'
note: candidate template ignored: couldn't infer template argument 'T'
I can get around using ReturnType
by creating an explicit specialisation of Wrapper
for Foo
. However, this requires duplicating all the code in Wrapper
(in my real life case it's a substantial class), when I just want to add some new functionality (as in ExtendedWrapper
). So, can this be done? What's wrong with the approach above?
c++ templates template-specialization specialization
1
One alternative is to have tag and then use overload::template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.
– Jarod42
Jan 2 at 17:54
add a comment |
I have a template class and a function with a template return type:
template<typename T>
class Wrapper {
public:
Wrapper(const T& _data) : data(_data) { }
const T& get_data() {return data;};
private:
T data;
};
template <typename T>
Wrapper<T> build_wrapped(){
T t{};
return Wrapper<T>(t);
}
Suppose that I want to extend the returned Wrapper
for one specific type T
and specialise the build_wrapped()
function for the type. So, let's create a template to hold the return type and use it in build_wrapped()
:
template<typename T>
struct ReturnType {
using type = Wrapper<T>;
};
template <typename T>
typename ReturnType<T>::type build_wrapped(){
T t{};
return typename ReturnType<T>::type(t);
}
And use it to provide the specialization:
struct Foo{};
class ExtendedWrapper : public Wrapper<Foo> {
public:
ExtendedWrapper(const Foo& _data) : Wrapper(_data) {}
int get_answer() {return 42;};
};
template<>
struct ReturnType<Foo> {
using type = ExtendedWrapper;
};
template<>
typename ReturnType<Foo>::type build_wrapped(){
Foo t{};
return typename ReturnType<Foo>::type(t);
}
However, the final declaration is rejected by both gcc and clang. For example, clang returns:
error: no function template matches function template specialization
'build_wrapped'
note: candidate template ignored: couldn't infer template argument 'T'
I can get around using ReturnType
by creating an explicit specialisation of Wrapper
for Foo
. However, this requires duplicating all the code in Wrapper
(in my real life case it's a substantial class), when I just want to add some new functionality (as in ExtendedWrapper
). So, can this be done? What's wrong with the approach above?
c++ templates template-specialization specialization
I have a template class and a function with a template return type:
template<typename T>
class Wrapper {
public:
Wrapper(const T& _data) : data(_data) { }
const T& get_data() {return data;};
private:
T data;
};
template <typename T>
Wrapper<T> build_wrapped(){
T t{};
return Wrapper<T>(t);
}
Suppose that I want to extend the returned Wrapper
for one specific type T
and specialise the build_wrapped()
function for the type. So, let's create a template to hold the return type and use it in build_wrapped()
:
template<typename T>
struct ReturnType {
using type = Wrapper<T>;
};
template <typename T>
typename ReturnType<T>::type build_wrapped(){
T t{};
return typename ReturnType<T>::type(t);
}
And use it to provide the specialization:
struct Foo{};
class ExtendedWrapper : public Wrapper<Foo> {
public:
ExtendedWrapper(const Foo& _data) : Wrapper(_data) {}
int get_answer() {return 42;};
};
template<>
struct ReturnType<Foo> {
using type = ExtendedWrapper;
};
template<>
typename ReturnType<Foo>::type build_wrapped(){
Foo t{};
return typename ReturnType<Foo>::type(t);
}
However, the final declaration is rejected by both gcc and clang. For example, clang returns:
error: no function template matches function template specialization
'build_wrapped'
note: candidate template ignored: couldn't infer template argument 'T'
I can get around using ReturnType
by creating an explicit specialisation of Wrapper
for Foo
. However, this requires duplicating all the code in Wrapper
(in my real life case it's a substantial class), when I just want to add some new functionality (as in ExtendedWrapper
). So, can this be done? What's wrong with the approach above?
c++ templates template-specialization specialization
c++ templates template-specialization specialization
asked Jan 2 at 17:26
user44168user44168
601210
601210
1
One alternative is to have tag and then use overload::template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.
– Jarod42
Jan 2 at 17:54
add a comment |
1
One alternative is to have tag and then use overload::template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.
– Jarod42
Jan 2 at 17:54
1
1
One alternative is to have tag and then use overload::
template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.– Jarod42
Jan 2 at 17:54
One alternative is to have tag and then use overload::
template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.– Jarod42
Jan 2 at 17:54
add a comment |
1 Answer
1
active
oldest
votes
The compiler already told you what the problem is:
note: candidate template ignored: couldn't infer template argument 'T'
You need to specify the template parameter explicitly.
template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ // ^~~~~
Foo t{};
return typename ReturnType<Foo>::type(t);
}
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
add a comment |
Your Answer
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%2f54010630%2fhow-to-use-derived-type-in-specialisation-of-return-type-function-template-co%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The compiler already told you what the problem is:
note: candidate template ignored: couldn't infer template argument 'T'
You need to specify the template parameter explicitly.
template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ // ^~~~~
Foo t{};
return typename ReturnType<Foo>::type(t);
}
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
add a comment |
The compiler already told you what the problem is:
note: candidate template ignored: couldn't infer template argument 'T'
You need to specify the template parameter explicitly.
template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ // ^~~~~
Foo t{};
return typename ReturnType<Foo>::type(t);
}
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
add a comment |
The compiler already told you what the problem is:
note: candidate template ignored: couldn't infer template argument 'T'
You need to specify the template parameter explicitly.
template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ // ^~~~~
Foo t{};
return typename ReturnType<Foo>::type(t);
}
The compiler already told you what the problem is:
note: candidate template ignored: couldn't infer template argument 'T'
You need to specify the template parameter explicitly.
template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ // ^~~~~
Foo t{};
return typename ReturnType<Foo>::type(t);
}
answered Jan 2 at 17:30


HolyBlackCatHolyBlackCat
17.1k33568
17.1k33568
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
add a comment |
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
Good catch! Thanks!
– user44168
Jan 2 at 17:34
Good catch! Thanks!
– user44168
Jan 2 at 17:34
1
1
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@user44168 If the answer solved your problem you should mark it as accepted to indicate that (and give the person answering a bit of rep), not just comment "good catch".
– Jesper Juhl
Jan 2 at 17:37
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
@JesperJuhl yeah, well, SO forces you to wait until 10 minutes had passed since posting before you can accept.
– user44168
Jan 2 at 17:48
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%2f54010630%2fhow-to-use-derived-type-in-specialisation-of-return-type-function-template-co%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
1
One alternative is to have tag and then use overload::
template <typename T> struct tag{}; template <typename T> Wrapper<T> build_wrapped(tag<T>) { return Wrapper<T>{{}};} ExtendedWrapper build_wrapped(tag<Foo>) { return ExtendedWrapper{{}};}
.– Jarod42
Jan 2 at 17:54