You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用C++模板进一步压缩字符串拼接函数的重载实现?

Can We Reduce the Join Functions to Two Templates?

Absolutely! You can condense your implementation down to two public template functions—one for string-style delimiters (including std::basic_string<T>, const char*, and const wchar_t*) and another for single-character delimiters (char and wchar_t). Here's a clean, efficient way to do it using a private core implementation and C++17's if constexpr for type deduction:

Full Implementation Code

#include <iostream>
#include <locale>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>

// Private core implementation (does the actual joining logic)
template <typename T, typename Arg, typename... Args>
std::basic_string<T> join_impl(
    const std::basic_string<T>& delimiter, const Arg& arg, const Args&... args) {
    if (!sizeof...(args)) {
        return arg;
    }
    std::basic_ostringstream<T> os;
    os << arg;
    static_cast<void>(std::initializer_list<int>{(os << delimiter << args, 0)...});
    return os.str();
}

// Public template 1: Handles string-style delimiters (basic_string, const char*, const wchar_t*)
template <typename Delimiter, typename Arg, typename... Args>
auto join(const Delimiter& delimiter, const Arg& arg, const Args&... args) {
    using namespace std;
    using DecayDelim = decay_t<Delimiter>;

    if constexpr (is_same_v<DecayDelim, const char*> || is_same_v<DecayDelim, char*>) {
        using T = char;
        return join_impl<T>(basic_string<T>(delimiter), arg, args...);
    } else if constexpr (is_same_v<DecayDelim, const wchar_t*> || is_same_v<DecayDelim, wchar_t*>) {
        using T = wchar_t;
        return join_impl<T>(basic_string<T>(delimiter), arg, args...);
    } else if constexpr (is_same_v<DecayDelim, basic_string<char>>) {
        return join_impl<char>(delimiter, arg, args...);
    } else if constexpr (is_same_v<DecayDelim, basic_string<wchar_t>>) {
        return join_impl<wchar_t>(delimiter, arg, args...);
    } else {
        static_assert(false, "Unsupported delimiter type: only char/wchar_t, const char*/wchar_t*, and std::string/wstring are allowed");
    }
}

// Public template 2: Handles single-character delimiters (char, wchar_t)
template <typename T, typename Arg, typename... Args>
std::basic_string<T> join(T delimiter, const Arg& arg, const Args&... args) {
    static_assert(std::is_same_v<T, char> || std::is_same_v<T, wchar_t>, 
                  "Single-character delimiter must be char or wchar_t");
    return join_impl<T>(std::basic_string<T>(1, delimiter), arg, args...);
}

int main(int argc, char** argv) {
    std::wcout.imbue(std::locale("zh_CN.UTF-8"));
    std::cout << join(' ', "1", "2", "3") << std::endl;
    std::wcout << join(L' ', L"一", L"二", L"三") << std::endl;
    std::cout << join(std::string("--"), "1", "2", "3") << std::endl;
    std::cout << join("--", "1", "2", "3") << std::endl;
    std::wcout << join(std::wstring(L"--"), L"一", L"二", L"三") << std::endl;
    std::wcout << join(L"--", L"一", L"二", L"三") << std::endl;
    return 0;
}

How It Works

  1. Core Logic (join_impl): This is your original joining logic, untouched. It takes a std::basic_string<T> delimiter and handles string concatenation via std::basic_ostringstream.
  2. String-Style Delimiters: The first public template uses if constexpr to inspect the delimiter type at compile time:
    • Converts const char*/char* to std::string and routes to join_impl<char>
    • Converts const wchar_t*/wchar_t* to std::wstring and routes to join_impl<wchar_t>
    • Passes existing std::string/std::wstring directly to the matching join_impl specialization
  3. Single-Character Delimiters: The second public template accepts char or wchar_t, creates a single-character std::basic_string<T>, and routes it to join_impl. The static_assert ensures only valid character types are used.

Key Benefits

  • Preserves All Original Functionality: Every test case from your original code will work exactly as before.
  • Cleaner Interface: Only two public functions to remember, grouped logically by delimiter type.
  • Compile-Time Safety: static_assert checks prevent invalid delimiter types from being used accidentally.

Note for C++14 or Earlier

If you're not using C++17, you can replace the if constexpr with SFINAE (using std::enable_if) to achieve the same type deduction. However, if constexpr provides a far more readable and maintainable solution.

内容的提问来源于stack exchange,提问作者Saddle Point

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:10:01