CRTP applied on a template class












1















Let's consider a CRTP template class Print which is meant to print the derived class:



template <typename T>
struct Print {
auto print() const -> void;
auto self() const -> T const & {
return static_cast<T const &>(*this);
}

private:
Print() {}
~Print() {}

friend T;
};


Because I want to specialize print based on the derived class like we could do this with an override, I don't implement the method yet.



We can wrap an Integer and do so for example:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend Print<Integer>;
};

template <>
auto Print<Integer>::print() const -> void {
std::cout << self().m_i << std::endl;
}


This works so far, now let's say I want to Print a generic version of a wrapper:



template <typename T>
class Wrapper :
public Print<Wrapper<T>>
{
public:
Wrapper(T value) : m_value(std::move(value)) {}

private:
T m_value;

friend Print<Wrapper<T>>;
};


If I specialize my print method with a specialization of the Wrapper it compile and works:



template <>
auto Print<Wrapper<int>>::print() const -> void
{
cout << self().m_value << endl;
}


But if I want to say "for all specializations of Wrapper, do that", it doesn't work:



template <typename T>
auto Print<Wrapper<T>>::print() const -> void
{
cout << self().m_value << endl;
}


If I run this over the following main function:



auto main(int, char**) -> int {
auto i = Integer{5};
i.print();

auto wrapper = Wrapper<int>{5};
wrapper.print();

return 0;
}


The compiler print:



50:42: error: invalid use of incomplete type 'struct Print<Wrapper<T> >'
6:8: error: declaration of 'struct Print<Wrapper<T> >'


Why ? How can I do that ? Is it even possible or do I have to make a complete specialization of my CRTP class ?










share|improve this question




















  • 1





    Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

    – luk32
    Nov 15 '18 at 15:06






  • 1





    I don't use trailing return types much, but does self return a copy of this?

    – François Andrieux
    Nov 15 '18 at 15:07











  • Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

    – Steranoid
    Nov 15 '18 at 15:15











  • Yoda notation why like you? auto print() const -> void;

    – SergeyA
    Nov 15 '18 at 15:24











  • I like rust ... Well, that's pretty much the only reason :P

    – Steranoid
    Nov 15 '18 at 15:25
















1















Let's consider a CRTP template class Print which is meant to print the derived class:



template <typename T>
struct Print {
auto print() const -> void;
auto self() const -> T const & {
return static_cast<T const &>(*this);
}

private:
Print() {}
~Print() {}

friend T;
};


Because I want to specialize print based on the derived class like we could do this with an override, I don't implement the method yet.



We can wrap an Integer and do so for example:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend Print<Integer>;
};

template <>
auto Print<Integer>::print() const -> void {
std::cout << self().m_i << std::endl;
}


This works so far, now let's say I want to Print a generic version of a wrapper:



template <typename T>
class Wrapper :
public Print<Wrapper<T>>
{
public:
Wrapper(T value) : m_value(std::move(value)) {}

private:
T m_value;

friend Print<Wrapper<T>>;
};


If I specialize my print method with a specialization of the Wrapper it compile and works:



template <>
auto Print<Wrapper<int>>::print() const -> void
{
cout << self().m_value << endl;
}


But if I want to say "for all specializations of Wrapper, do that", it doesn't work:



template <typename T>
auto Print<Wrapper<T>>::print() const -> void
{
cout << self().m_value << endl;
}


If I run this over the following main function:



auto main(int, char**) -> int {
auto i = Integer{5};
i.print();

auto wrapper = Wrapper<int>{5};
wrapper.print();

return 0;
}


The compiler print:



50:42: error: invalid use of incomplete type 'struct Print<Wrapper<T> >'
6:8: error: declaration of 'struct Print<Wrapper<T> >'


Why ? How can I do that ? Is it even possible or do I have to make a complete specialization of my CRTP class ?










share|improve this question




















  • 1





    Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

    – luk32
    Nov 15 '18 at 15:06






  • 1





    I don't use trailing return types much, but does self return a copy of this?

    – François Andrieux
    Nov 15 '18 at 15:07











  • Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

    – Steranoid
    Nov 15 '18 at 15:15











  • Yoda notation why like you? auto print() const -> void;

    – SergeyA
    Nov 15 '18 at 15:24











  • I like rust ... Well, that's pretty much the only reason :P

    – Steranoid
    Nov 15 '18 at 15:25














1












1








1








Let's consider a CRTP template class Print which is meant to print the derived class:



template <typename T>
struct Print {
auto print() const -> void;
auto self() const -> T const & {
return static_cast<T const &>(*this);
}

private:
Print() {}
~Print() {}

friend T;
};


Because I want to specialize print based on the derived class like we could do this with an override, I don't implement the method yet.



We can wrap an Integer and do so for example:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend Print<Integer>;
};

template <>
auto Print<Integer>::print() const -> void {
std::cout << self().m_i << std::endl;
}


This works so far, now let's say I want to Print a generic version of a wrapper:



template <typename T>
class Wrapper :
public Print<Wrapper<T>>
{
public:
Wrapper(T value) : m_value(std::move(value)) {}

private:
T m_value;

friend Print<Wrapper<T>>;
};


If I specialize my print method with a specialization of the Wrapper it compile and works:



template <>
auto Print<Wrapper<int>>::print() const -> void
{
cout << self().m_value << endl;
}


But if I want to say "for all specializations of Wrapper, do that", it doesn't work:



template <typename T>
auto Print<Wrapper<T>>::print() const -> void
{
cout << self().m_value << endl;
}


If I run this over the following main function:



auto main(int, char**) -> int {
auto i = Integer{5};
i.print();

auto wrapper = Wrapper<int>{5};
wrapper.print();

return 0;
}


The compiler print:



50:42: error: invalid use of incomplete type 'struct Print<Wrapper<T> >'
6:8: error: declaration of 'struct Print<Wrapper<T> >'


Why ? How can I do that ? Is it even possible or do I have to make a complete specialization of my CRTP class ?










share|improve this question
















Let's consider a CRTP template class Print which is meant to print the derived class:



template <typename T>
struct Print {
auto print() const -> void;
auto self() const -> T const & {
return static_cast<T const &>(*this);
}

private:
Print() {}
~Print() {}

friend T;
};


Because I want to specialize print based on the derived class like we could do this with an override, I don't implement the method yet.



We can wrap an Integer and do so for example:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend Print<Integer>;
};

template <>
auto Print<Integer>::print() const -> void {
std::cout << self().m_i << std::endl;
}


This works so far, now let's say I want to Print a generic version of a wrapper:



template <typename T>
class Wrapper :
public Print<Wrapper<T>>
{
public:
Wrapper(T value) : m_value(std::move(value)) {}

private:
T m_value;

friend Print<Wrapper<T>>;
};


If I specialize my print method with a specialization of the Wrapper it compile and works:



template <>
auto Print<Wrapper<int>>::print() const -> void
{
cout << self().m_value << endl;
}


But if I want to say "for all specializations of Wrapper, do that", it doesn't work:



template <typename T>
auto Print<Wrapper<T>>::print() const -> void
{
cout << self().m_value << endl;
}


If I run this over the following main function:



auto main(int, char**) -> int {
auto i = Integer{5};
i.print();

auto wrapper = Wrapper<int>{5};
wrapper.print();

return 0;
}


The compiler print:



50:42: error: invalid use of incomplete type 'struct Print<Wrapper<T> >'
6:8: error: declaration of 'struct Print<Wrapper<T> >'


Why ? How can I do that ? Is it even possible or do I have to make a complete specialization of my CRTP class ?







c++ c++11 crtp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 15 '18 at 15:14







Steranoid

















asked Nov 15 '18 at 14:59









SteranoidSteranoid

485




485








  • 1





    Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

    – luk32
    Nov 15 '18 at 15:06






  • 1





    I don't use trailing return types much, but does self return a copy of this?

    – François Andrieux
    Nov 15 '18 at 15:07











  • Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

    – Steranoid
    Nov 15 '18 at 15:15











  • Yoda notation why like you? auto print() const -> void;

    – SergeyA
    Nov 15 '18 at 15:24











  • I like rust ... Well, that's pretty much the only reason :P

    – Steranoid
    Nov 15 '18 at 15:25














  • 1





    Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

    – luk32
    Nov 15 '18 at 15:06






  • 1





    I don't use trailing return types much, but does self return a copy of this?

    – François Andrieux
    Nov 15 '18 at 15:07











  • Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

    – Steranoid
    Nov 15 '18 at 15:15











  • Yoda notation why like you? auto print() const -> void;

    – SergeyA
    Nov 15 '18 at 15:24











  • I like rust ... Well, that's pretty much the only reason :P

    – Steranoid
    Nov 15 '18 at 15:25








1




1





Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

– luk32
Nov 15 '18 at 15:06





Can you post a complete example? My initial hunch is that auto self() const -> T is the culprit, since you actually return whole object. Even though the body casts to a reference return would copy the object. I am to lazy to compile a live example to test.

– luk32
Nov 15 '18 at 15:06




1




1





I don't use trailing return types much, but does self return a copy of this?

– François Andrieux
Nov 15 '18 at 15:07





I don't use trailing return types much, but does self return a copy of this?

– François Andrieux
Nov 15 '18 at 15:07













Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

– Steranoid
Nov 15 '18 at 15:15





Yes you're right I did a copy, I didn't pay attention, but on an int this doesn't solve anything anyway. I corrected it though and add a main function.

– Steranoid
Nov 15 '18 at 15:15













Yoda notation why like you? auto print() const -> void;

– SergeyA
Nov 15 '18 at 15:24





Yoda notation why like you? auto print() const -> void;

– SergeyA
Nov 15 '18 at 15:24













I like rust ... Well, that's pretty much the only reason :P

– Steranoid
Nov 15 '18 at 15:25





I like rust ... Well, that's pretty much the only reason :P

– Steranoid
Nov 15 '18 at 15:25












1 Answer
1






active

oldest

votes


















1














You can do this in a bit of a roundabout way so long as you're careful.



Live Demo



Your Print class will rely on yet another class PrintImpl to do the printing.



#include <type_traits>

template<class...>
struct always_false : std::false_type{};

template<class T>
struct PrintImpl
{
void operator()(const T&) const
{
static_assert(always_false<T>::value, "PrintImpl hasn't been specialized for T");
}
};


You'll partially specialize this PrintImpl for your Wrapper class:



template<class T>
struct PrintImpl<Wrapper<T>>
{
void operator()(const Wrapper<T>& _val) const
{
std::cout << _val.m_value;
}
};


And make sure that Wrapper declares this PrintImpl to be a friend:



friend struct PrintImpl<Wrapper<T>>;


The Print class creates an instance of PrintImpl and calls operator():



void print() const
{
PrintImpl<T>{}(self());
}


This works so long as your specializations are declared before you actually instantiate an instance of the Print class.





You can also fully specialize PrintImpl<T>::operator() for your Integer class without writing a class specialization:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend PrintImpl<Integer>;
};

template <>
void PrintImpl<Integer>::operator()(const Integer& wrapper) const {
std::cout << wrapper.m_i << std::endl;
}





share|improve this answer


























  • That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

    – Steranoid
    Nov 15 '18 at 15:20











  • @Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

    – AndyG
    Nov 15 '18 at 15:21






  • 2





    1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

    – Dark Falcon
    Nov 15 '18 at 15:22













  • What's the purpose of always_false here?

    – bipll
    Nov 15 '18 at 16:03






  • 1





    @Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

    – AndyG
    Nov 16 '18 at 15:53











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%2f53322234%2fcrtp-applied-on-a-template-class%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









1














You can do this in a bit of a roundabout way so long as you're careful.



Live Demo



Your Print class will rely on yet another class PrintImpl to do the printing.



#include <type_traits>

template<class...>
struct always_false : std::false_type{};

template<class T>
struct PrintImpl
{
void operator()(const T&) const
{
static_assert(always_false<T>::value, "PrintImpl hasn't been specialized for T");
}
};


You'll partially specialize this PrintImpl for your Wrapper class:



template<class T>
struct PrintImpl<Wrapper<T>>
{
void operator()(const Wrapper<T>& _val) const
{
std::cout << _val.m_value;
}
};


And make sure that Wrapper declares this PrintImpl to be a friend:



friend struct PrintImpl<Wrapper<T>>;


The Print class creates an instance of PrintImpl and calls operator():



void print() const
{
PrintImpl<T>{}(self());
}


This works so long as your specializations are declared before you actually instantiate an instance of the Print class.





You can also fully specialize PrintImpl<T>::operator() for your Integer class without writing a class specialization:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend PrintImpl<Integer>;
};

template <>
void PrintImpl<Integer>::operator()(const Integer& wrapper) const {
std::cout << wrapper.m_i << std::endl;
}





share|improve this answer


























  • That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

    – Steranoid
    Nov 15 '18 at 15:20











  • @Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

    – AndyG
    Nov 15 '18 at 15:21






  • 2





    1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

    – Dark Falcon
    Nov 15 '18 at 15:22













  • What's the purpose of always_false here?

    – bipll
    Nov 15 '18 at 16:03






  • 1





    @Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

    – AndyG
    Nov 16 '18 at 15:53
















1














You can do this in a bit of a roundabout way so long as you're careful.



Live Demo



Your Print class will rely on yet another class PrintImpl to do the printing.



#include <type_traits>

template<class...>
struct always_false : std::false_type{};

template<class T>
struct PrintImpl
{
void operator()(const T&) const
{
static_assert(always_false<T>::value, "PrintImpl hasn't been specialized for T");
}
};


You'll partially specialize this PrintImpl for your Wrapper class:



template<class T>
struct PrintImpl<Wrapper<T>>
{
void operator()(const Wrapper<T>& _val) const
{
std::cout << _val.m_value;
}
};


And make sure that Wrapper declares this PrintImpl to be a friend:



friend struct PrintImpl<Wrapper<T>>;


The Print class creates an instance of PrintImpl and calls operator():



void print() const
{
PrintImpl<T>{}(self());
}


This works so long as your specializations are declared before you actually instantiate an instance of the Print class.





You can also fully specialize PrintImpl<T>::operator() for your Integer class without writing a class specialization:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend PrintImpl<Integer>;
};

template <>
void PrintImpl<Integer>::operator()(const Integer& wrapper) const {
std::cout << wrapper.m_i << std::endl;
}





share|improve this answer


























  • That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

    – Steranoid
    Nov 15 '18 at 15:20











  • @Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

    – AndyG
    Nov 15 '18 at 15:21






  • 2





    1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

    – Dark Falcon
    Nov 15 '18 at 15:22













  • What's the purpose of always_false here?

    – bipll
    Nov 15 '18 at 16:03






  • 1





    @Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

    – AndyG
    Nov 16 '18 at 15:53














1












1








1







You can do this in a bit of a roundabout way so long as you're careful.



Live Demo



Your Print class will rely on yet another class PrintImpl to do the printing.



#include <type_traits>

template<class...>
struct always_false : std::false_type{};

template<class T>
struct PrintImpl
{
void operator()(const T&) const
{
static_assert(always_false<T>::value, "PrintImpl hasn't been specialized for T");
}
};


You'll partially specialize this PrintImpl for your Wrapper class:



template<class T>
struct PrintImpl<Wrapper<T>>
{
void operator()(const Wrapper<T>& _val) const
{
std::cout << _val.m_value;
}
};


And make sure that Wrapper declares this PrintImpl to be a friend:



friend struct PrintImpl<Wrapper<T>>;


The Print class creates an instance of PrintImpl and calls operator():



void print() const
{
PrintImpl<T>{}(self());
}


This works so long as your specializations are declared before you actually instantiate an instance of the Print class.





You can also fully specialize PrintImpl<T>::operator() for your Integer class without writing a class specialization:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend PrintImpl<Integer>;
};

template <>
void PrintImpl<Integer>::operator()(const Integer& wrapper) const {
std::cout << wrapper.m_i << std::endl;
}





share|improve this answer















You can do this in a bit of a roundabout way so long as you're careful.



Live Demo



Your Print class will rely on yet another class PrintImpl to do the printing.



#include <type_traits>

template<class...>
struct always_false : std::false_type{};

template<class T>
struct PrintImpl
{
void operator()(const T&) const
{
static_assert(always_false<T>::value, "PrintImpl hasn't been specialized for T");
}
};


You'll partially specialize this PrintImpl for your Wrapper class:



template<class T>
struct PrintImpl<Wrapper<T>>
{
void operator()(const Wrapper<T>& _val) const
{
std::cout << _val.m_value;
}
};


And make sure that Wrapper declares this PrintImpl to be a friend:



friend struct PrintImpl<Wrapper<T>>;


The Print class creates an instance of PrintImpl and calls operator():



void print() const
{
PrintImpl<T>{}(self());
}


This works so long as your specializations are declared before you actually instantiate an instance of the Print class.





You can also fully specialize PrintImpl<T>::operator() for your Integer class without writing a class specialization:



class Integer :
public Print<Integer>
{
public:
Integer(int i) : m_i(i) {}

private:
int m_i;

friend PrintImpl<Integer>;
};

template <>
void PrintImpl<Integer>::operator()(const Integer& wrapper) const {
std::cout << wrapper.m_i << std::endl;
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 20 '18 at 15:33

























answered Nov 15 '18 at 15:15









AndyGAndyG

26.8k77097




26.8k77097













  • That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

    – Steranoid
    Nov 15 '18 at 15:20











  • @Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

    – AndyG
    Nov 15 '18 at 15:21






  • 2





    1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

    – Dark Falcon
    Nov 15 '18 at 15:22













  • What's the purpose of always_false here?

    – bipll
    Nov 15 '18 at 16:03






  • 1





    @Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

    – AndyG
    Nov 16 '18 at 15:53



















  • That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

    – Steranoid
    Nov 15 '18 at 15:20











  • @Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

    – AndyG
    Nov 15 '18 at 15:21






  • 2





    1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

    – Dark Falcon
    Nov 15 '18 at 15:22













  • What's the purpose of always_false here?

    – bipll
    Nov 15 '18 at 16:03






  • 1





    @Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

    – AndyG
    Nov 16 '18 at 15:53

















That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

– Steranoid
Nov 15 '18 at 15:20





That's a nice way, isn't creating the PrintImpl each time the function is called a little bit heavy though ?

– Steranoid
Nov 15 '18 at 15:20













@Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

– AndyG
Nov 15 '18 at 15:21





@Steranoid: It's a necessary evil because you cannot partially specialize functions. So we have to use a class.

– AndyG
Nov 15 '18 at 15:21




2




2





1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

– Dark Falcon
Nov 15 '18 at 15:22







1. It is likely optimized away. 2. You can make the specialized function a static function instead--it wouldn't have to be operator().

– Dark Falcon
Nov 15 '18 at 15:22















What's the purpose of always_false here?

– bipll
Nov 15 '18 at 16:03





What's the purpose of always_false here?

– bipll
Nov 15 '18 at 16:03




1




1





@Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

– AndyG
Nov 16 '18 at 15:53





@Steranoid: Fair enough, I see your point. I think that we can get the full function specialization you desire as well as the safety of the static_assert from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh

– AndyG
Nov 16 '18 at 15:53




















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%2f53322234%2fcrtp-applied-on-a-template-class%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

Bressuire

Vorschmack

Quarantine