如何声明对字符串无助的政策类,与其他政策具有一致的签名,并在编译时进行评估

发布于 2025-02-09 06:00:41 字数 1485 浏览 0 评论 0原文

我正在整理一组策略类,这些策略类可操作许多操作到字符串。我希望这些策略可以交换,但是“无所事事”的政策也很有问题,因为:

  1. 我看不到如何避免使用移动语义复制,同时与姐妹策略保持相同的(非移动)
  2. 接口编译器应该知道,可以在编译时对策略的调用进行内衬和评估,但是它不接受constexpr,因为返回类型是字符串。
#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
}

在这种情况下,“标准”的方法是什么?

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:

  1. I don't see how to avoid copy using move semantic while maintaining the same (non-move) interface with the sister policies
  2. 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

Smile简单爱 2025-02-16 06:00:41

您想要的是减少不必要的副本,并且在调用编辑时不要使用std ::移动。为什么不返回const引用?

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]");

请参阅在线演示

关于您的第二个问题,因为C ++ 20,std :: string string可以是字面类型。

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]");

在C ++ 20中完全可以,请参见 demo

但是,由于您的变量s不能为constexpr(它在运行时创建),因此这里没有很大的帮助。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文