How to use derived type in specialisation of return-type function template? (“couldn't infer template...












0















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?










share|improve this question


















  • 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
















0















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?










share|improve this question


















  • 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














0












0








0


1






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?










share|improve this question














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






share|improve this question













share|improve this question











share|improve this question




share|improve this question










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














  • 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












1 Answer
1






active

oldest

votes


















4














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);
}





share|improve this answer
























  • 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












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
});


}
});














draft saved

draft discarded


















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









4














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);
}





share|improve this answer
























  • 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
















4














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);
}





share|improve this answer
























  • 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














4












4








4







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);
}





share|improve this answer













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);
}






share|improve this answer












share|improve this answer



share|improve this answer










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



















  • 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




















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith