CRTP applied on a template class
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
add a comment |
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
1
Can you post a complete example? My initial hunch is thatauto 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 doesself
return a copy ofthis
?
– 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
add a comment |
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
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
c++ c++11 crtp
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 thatauto 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 doesself
return a copy ofthis
?
– 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
add a comment |
1
Can you post a complete example? My initial hunch is thatauto 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 doesself
return a copy ofthis
?
– 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
add a comment |
1 Answer
1
active
oldest
votes
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;
}
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 beoperator()
.
– Dark Falcon
Nov 15 '18 at 15:22
What's the purpose ofalways_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 thestatic_assert
from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh
– AndyG
Nov 16 '18 at 15:53
|
show 12 more comments
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%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
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;
}
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 beoperator()
.
– Dark Falcon
Nov 15 '18 at 15:22
What's the purpose ofalways_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 thestatic_assert
from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh
– AndyG
Nov 16 '18 at 15:53
|
show 12 more comments
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;
}
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 beoperator()
.
– Dark Falcon
Nov 15 '18 at 15:22
What's the purpose ofalways_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 thestatic_assert
from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh
– AndyG
Nov 16 '18 at 15:53
|
show 12 more comments
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;
}
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;
}
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 beoperator()
.
– Dark Falcon
Nov 15 '18 at 15:22
What's the purpose ofalways_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 thestatic_assert
from my code (and no extra inheritance): wandbox.org/permlink/VFPy7rTdXm9I3fYh
– AndyG
Nov 16 '18 at 15:53
|
show 12 more comments
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 beoperator()
.
– Dark Falcon
Nov 15 '18 at 15:22
What's the purpose ofalways_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 thestatic_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
|
show 12 more comments
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%2f53322234%2fcrtp-applied-on-a-template-class%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
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 ofthis
?– 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