マップ内の要素を追跡するためのキーとしてタプルを使用し、後でマップを反復処理してマップの文字列バージョンを生成しています。変換を支援するために、キーとして使用されるタプルを連結するテンプレートの便利な関数があります (この回答に触発されました)。
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
template<std::size_t idx = 0, typename ...T>
inline typename std::enable_if<idx == sizeof...(T), void>::type
cat_tuple(std::tuple<T...> &t, std::stringstream &s){
}
template<std::size_t idx = 0, typename ...T>
inline typename std::enable_if<idx < sizeof...(T), void>::type
cat_tuple(std::tuple<T...> &t, std::stringstream &s){
if (idx != 0)
s << ",";
s << std::get<idx>(t);
cat_tuple<idx+1, T...>(t, s);
}
typedef std::tuple<int, int> my_tuple;
int main(){
my_tuple t(1, 2);
std::stringstream s;
cat_tuple(t, s);
std::cout << s.str() << std::endl; //Correctly prints "1,2"
}
要素をマップに挿入し、エラーなしで繰り返すことができます
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
#include <map>
typedef std::tuple<int, int> my_tuple;
typedef std::map<my_tuple, int> my_map;
int main(){
my_map m;
my_tuple t(1, 2);
m.insert(std::pair<my_tuple, int>(t, 1));
std::stringstream s;
for(my_map::iterator i = m.begin(); i != m.end(); ++i)
s << i->second;
std::cout << s.str() << std::endl; //Correctly prints "1"
}
しかし、マップを反復しようとすると、置換エラーが発生します。
#include <iostream>
#include <string>
#include <sstream>
#include <tuple>
#include <map>
template<std::size_t idx = 0, typename ...T>
inline typename std::enable_if<idx == sizeof...(T), void>::type
cat_tuple(std::tuple<T...> &t, std::stringstream &s){
}
template<std::size_t idx = 0, typename ...T>
inline typename std::enable_if<idx < sizeof...(T), void>::type
cat_tuple(std::tuple<T...> &t, std::stringstream &s){
if (idx != 0)
s << ",";
s << std::get<idx>(t);
cat_tuple<idx+1, T...>(t, s);
}
typedef std::tuple<int, int> my_tuple;
typedef std::map<my_tuple, int> my_map;
int main(){
my_map m;
my_tuple t(1, 2);
m.insert(std::pair<my_tuple, int>(t, 1));
std::stringstream s;
for(my_map::iterator i = m.begin(); i != m.end(); ++i){
if (i != m.begin())
s << "\n";
cat_tuple(i->first, s); //Substitution error, see below
s << " " << i->second;
}
std::cout << s.str() << std::endl;
}
生産 (OSX 上の g++ 4.2.1、余分な enable_if のメモを削除)
$ g++ asdf.cc -std=c++11
asdf.cc:31:3: error: no matching function for call to 'cat_tuple'
cat_tuple(i->first, s); //Substitution error, see below
^~~~~~~~~
...
asdf.cc:14:1: note: candidate template ignored: substitution failure [with idx =
0, T = <int, int>]
cat_tuple(std::tuple<T...> &t, std::stringstream &s){
^
1 error generated.
エラーメッセージにあるように、使用したいテンプレートは、置換の失敗により無視されました。マップに移動したときにどのような違いが生じましたか? また、どのように修正しますか?