I am putting together a set of policy classes that operate a number of operations to a string. I would like these policies to be exchangeable, but the "do nothing" policy is problematic too me, as:
- I don't see how to avoid copy using move semantic while maintaining the same (non-move) interface with the sister policies
- The compiler should know that the call to the policy can be inlined and evaluated at compile time, but it does not accept
constexpr
because the return type is a string.
#include <string>
#include<regex>
#include<cassert>
///
/// @brief Do not change anything
///
struct identity
{
static std::string edit(std::string&& s) // can not use constexpr: return type not a literal
{
return std::move(s);
}
};
///
/// @brief Template class.
///
template<unsigned int N>
struct remove_comments_of_depth
{};
///
/// @brief Do not remove anything
///
template<> struct remove_comments_of_depth<0> : identity
{};
///
/// @brief Remove all comments substrings contained between square brackets
///
/// @note Assumes that text is well formatted so there are no such things like [[]] or unclosed bracket
///
template<> struct remove_comments_of_depth<1>
{
static std::string edit(const std::string& s)
{
return std::regex_replace(s, std::regex(R"(\[[^()]*\])"), "");
}
};
int main(int argc, char *argv[])
{
std::string s = "my_string[this is a comment]";
auto copy = s;
assert(remove_comments_of_depth<1>::edit(s) == "my_string");
assert(remove_comments_of_depth<0>::edit(std::move(copy)) == s); // <<< how to avoid this call to std::move
}
What is the "standard" way to go in this kind of situation?
CodePudding user response:
What you want here is reduce unnecessary copy and don't use std::move
when calling edit
. Why not just return a const reference?
struct identity
{
static const std::string& edit(const std::string& s) {
return s;
}
};
std::string s = "my_string[this is a comment]";
assert(remove_comments_of_depth<0>::edit("my_string[this is a comment]") == "my_string[this is a comment]");
assert(remove_comments_of_depth<0>::edit(s) == "my_string[this is a comment]");
See Online Demo
As to your second question, since C 20, std::string
can be a literal type.
struct identity
{
constexpr static std::string edit(std::string&& s) {
return s;
}
};
static_assert(remove_comments_of_depth<0>::edit("my_string[this is a comment]") == "my_string[this is a comment]");
It's totally fine in C 20, see Demo.
But since your variable s
can't be constexpr
(it's created at run-time), there's no big help here.