C++ で可変長引数を使って文字列を連結する

C++ で文字列連結を行う方法はいくつかあるが,単一式で書けなかったり,STL コンテナを使ったりなど,どれも気軽には使いにくい感がある. 今回は可変長引数を使って,使い勝手のよい文字列連結関数を実装した.

背景

次のコードは,文字列連結についての2つの問題を,C++ の標準的な方法で実装したものである.

//! Example 1: "usr", "bin", "gcc" -> "/usr/bin/gcc"
// +
return "/" + "usr" + "/" + "bin" + "/" + "gcc";

// stringstream
stringstream ss;
ss << "/" << "usr" << "/" << "bin" << "/" << "gcc";
return ss.str();

// boost::algorithm::join
std::vector<std::string> v = {"", "usr", "bin", "gcc"};
return boost::algorithm::join(v, "/");

//! Example 2: "image", 2014, "summer.png" -> "image-2014-summer.png"
// +
return "image" + "-" + 2014 + "-" + "gcc"; // Error!
return "image" + "-" + itoa(2014) + "-" + "gcc"; // Not standard

// stringstream
stringstream ss;
ss << "image" << "-" << 2014 << "-" << "summer.png";
return ss.str();

// boost::algorithm::join
? v = {"image", 2014, "summer.png"}; // Which type to use?
return boost::algorithm::join(v, "-");

C++ で文字列連結をしようと思うと上の3通りが標準的だと思うが,どれも短所がある. + を使う方法は型の制限がきつく,boost::algorithm::join は一度コンテナを作らなければいけない. 唯一2問目を解ける stringstream でも,単一式として書くことができず,最低でも3文を書かなければならないという欠点がある.

というわけで今回の目標は,混合型で使えて,かつ式として書ける文字列連結関数 Join を実装することである.インターフェースは次のようになる.

return Join("/", "", "usr", "bin", "gcc");
return Join("-", "image", 2014, "summer.png");

本当は Join("image", 2014, "summer.png", sep="-") と書きたいところだが,C++ の制約上可変長引数と名前付き引数が両立しないので,上の形で妥協することにする.

実装

#include <sstream>
#include <string>

template<typename T, typename U, typename... R>
void Join(std::stringstream& ss, const T& sep, const U& head, const R&... follows) {
	ss << head << sep;
	Join(ss, sep, follows...);
}

template<typename T, typename U>
void Join(std::stringstream& ss, const T& sep, const U& head) {
	ss << head;
}

template<typename T, typename U, typename... R>
std::string Join(const T& sep, const U& head, const R&... follows) {
	std::stringstream ss;
	Join(ss, sep, head, follows...);
	return ss.str();
}

C++ で可変長引数を使って文字列を連結する」への1件のフィードバック

  1. 返信

コメントを残す

メールアドレスが公開されることはありません。