Reputation: 2449
I have the following class:
template<typename T>
class Foo {
// ...
void frobnicate(const T& arg) {
// [lots of code here]
do_the_thing(arg);
// [lots of code here]
}
void frobnicate(T&& arg) {
// [lots of code here, same as above]
do_the_thing(std::move(arg));
// [lots of code here, same as above]
}
}
Is there a way to remove the code duplication between the two versions of frobnicate
without introducing "post" and "pre" helper functions?
Ideally, I'd like to write something like:
void frobnicate(/*what goes here?*/ arg) {
// [lots of code here]
if (is_rvalue_reference(arg))
do_the_thing(std::move(arg));
else
do_the_thing(arg);
// [lots of code here]
}
Is there a way to do this?
I think if T
wasn't a class template argument but a function template argument, I could probably use template argument deduction in some clever way (though I'm not sure how exactly I'd do that either), but with the class involved I am not sure where to start...
Upvotes: 2
Views: 520
Reputation: 172894
I think the best way is to make the function template and take advantage of the forwarding reference, which could reserve the value category of the argument.
template<typename T>
class Foo {
template <typename X>
void frobnicate(X&& arg) {
// [lots of code here]
do_the_thing(std::forward<X>(arg));
// [lots of code here]
}
};
If you want to restrict the type accepted by frobnicate
to be T
, you can apply static_assert
or std::enable_if
for frobnicate
, e.g.
template<typename T>
class Foo {
template <typename X>
void frobnicate(X&& arg) {
static_assert(std::is_same_v<T, std::decay_t<X>>, "X must be the same type of T");
// [lots of code here]
do_the_thing(std::forward<X>(arg));
// [lots of code here]
}
};
or
template<typename T>
class Foo {
template <typename X>
std::enable_if_t<std::is_same_v<T, std::decay_t<X>>> frobnicate(X&& arg) {
// [lots of code here]
do_the_thing(std::forward<X>(arg));
// [lots of code here]
}
};
Upvotes: 1