如果设置了可选函数参数,如何启用模板参数?

发布于 2025-02-02 05:25:14 字数 3650 浏览 4 评论 0原文

我有一个解析功能,我想根据设置长度选项是否设置。如果设置了长度选项,则该函数应始终检查缩短长度是否等于0。如果没有,则仅检查终止终止。 Based on this little detail I don't want to rewrite my whole function, so here's what I came up with:

#include <iostream>

const char* str = "some random string";

template <bool LengthOpt = false>
void parse(const char* ch, size_t len = 0)
{
    while ( 1 ) {
        if constexpr(LengthOpt) {
            if ( len == 0 ) {
                std::cout << std::endl;
                return ;
            } else {
                len--;
            }
        } else {
            if ( !(*ch) ) {
                std::cout << std::endl;
                return ;
            }
        }
        std::cout << *ch;
        ++ch;

        /* big part starts here */
    }
}

int main()
{
    parse<true>(str, 5);
    parse(str);
}

godbolt

让我困扰的是,我总是必须指定长度和模板参数才能使用长度选项。因此,我想知道:

  • 是否有一种方法可以根据设置可选参数来进行constexpr分支?
  • 我可以从设置可选参数中推断模板参数吗?

注意:这是一个人为的示例,只是显示细节。我在代码中添加了实际解析的评论。

I have a parsing function that I want to branch based on whether a length option is set or not. If the length option is set, the function should always check if the decreased length equals to 0. If not, it only checks for null termination. Based on this little detail I don't want to rewrite my whole function, so here's what I came up with:

#include <iostream>

const char* str = "some random string";

template <bool LengthOpt = false>
void parse(const char* ch, size_t len = 0)
{
    while ( 1 ) {
        if constexpr(LengthOpt) {
            if ( len == 0 ) {
                std::cout << std::endl;
                return ;
            } else {
                len--;
            }
        } else {
            if ( !(*ch) ) {
                std::cout << std::endl;
                return ;
            }
        }
        std::cout << *ch;
        ++ch;

        /* big part starts here */
    }
}

int main()
{
    parse<true>(str, 5);
    parse(str);
}

godbolt

What bugs me is that I always have to specify both, length AND template parameter to go with the length option. So I'm wondering:

  • Is there a way to constexpr branch based on whether an optional parameter is set or not?
  • Could I infer template parameters from whether the optional parameter is set?

Note: This is a contrived example showing just the detail. I've added comments in the code where the actual parsing would happen.

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

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

发布评论

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

评论(2

面犯桃花 2025-02-09 05:25:15

我认为您可以在此处使用功能过载:

#include <iostream>

const char* str = "some random string";

void parse(const char* ch, size_t len)
{
    while ( 1 ) {
        if ( len == 0 ) {
            std::cout << std::endl;
            return ;
        } else {
                len--;
        }

        std::cout << *ch;
        ++ch;

        /* the big part can be moved into separate function */
       bigPart(ch);
    }
}

void parse(const char* ch)
{
    while ( 1 ) {
        if ( !(*ch) ) {
            std::cout << std::endl;
            return ;
        }

        std::cout << *ch;
        ++ch;

        /* the big part can be moved into separate function */
       bigPart(ch);

    }
}

int main()
{
    parse(str, 5);
    parse(str);
}

I think you can use function overloading here:

#include <iostream>

const char* str = "some random string";

void parse(const char* ch, size_t len)
{
    while ( 1 ) {
        if ( len == 0 ) {
            std::cout << std::endl;
            return ;
        } else {
                len--;
        }

        std::cout << *ch;
        ++ch;

        /* the big part can be moved into separate function */
       bigPart(ch);
    }
}

void parse(const char* ch)
{
    while ( 1 ) {
        if ( !(*ch) ) {
            std::cout << std::endl;
            return ;
        }

        std::cout << *ch;
        ++ch;

        /* the big part can be moved into separate function */
       bigPart(ch);

    }
}

int main()
{
    parse(str, 5);
    parse(str);
}
没有你我更好 2025-02-09 05:25:15

您可以使用一对过载来执行此操作,该过载将其委派给模板版本以避免复制代码:

template <bool LengthOpt>
void do_parse(const char* ch, std::size_t len) {
    // ...
}

void parse(const char* ch) {
    do_parse<true>(ch, 0);
}

void parse(const char* ch, std::size_t len) {
    do_parse<false>(ch, len);
}

或者您可以切换到基于迭代的方法:

template<typename Iterator, typename Sentinel>
void do_parse(Iterator it, Sentinel end) {
    for (; it != end; ++it) {
        char c = *it;
        // ...
    }
}

struct null_sentinel_t {};
inline constexpr null_sentinel_t null_sentinel{};

inline constexpr bool operator==(null_sentinel_t, const char* p) noexcept { return *p == 0; }
// The next 3 overloads are not necessary in C++20
inline constexpr bool operator==(const char* p, null_sentinel_t) noexcept { return *p == 0; }
inline constexpr bool operator!=(null_sentinel_t, const char* p) noexcept { return *p != 0; }
inline constexpr bool operator!=(const char* p, null_sentinel_t) noexcept { return *p != 0; }

void parse(const char* ch) {
    do_parse(ch, null_sentinel);
}
void parse(const char* ch, std::size_t len) {
    do_parse(ch, ch + len);
}

You can do this with a pair of overloads that delegate to a templated version to avoid duplicating code:

template <bool LengthOpt>
void do_parse(const char* ch, std::size_t len) {
    // ...
}

void parse(const char* ch) {
    do_parse<true>(ch, 0);
}

void parse(const char* ch, std::size_t len) {
    do_parse<false>(ch, len);
}

Or you can switch to an iterator-based approach:

template<typename Iterator, typename Sentinel>
void do_parse(Iterator it, Sentinel end) {
    for (; it != end; ++it) {
        char c = *it;
        // ...
    }
}

struct null_sentinel_t {};
inline constexpr null_sentinel_t null_sentinel{};

inline constexpr bool operator==(null_sentinel_t, const char* p) noexcept { return *p == 0; }
// The next 3 overloads are not necessary in C++20
inline constexpr bool operator==(const char* p, null_sentinel_t) noexcept { return *p == 0; }
inline constexpr bool operator!=(null_sentinel_t, const char* p) noexcept { return *p != 0; }
inline constexpr bool operator!=(const char* p, null_sentinel_t) noexcept { return *p != 0; }

void parse(const char* ch) {
    do_parse(ch, null_sentinel);
}
void parse(const char* ch, std::size_t len) {
    do_parse(ch, ch + len);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文