模板函数中的静态变量失败
Static variable in template function fail
头文件(test.h):
#ifndef _test_h_
#define _test_h_
#include <string>
#include <sstream>
#include <map>
typedef std::map<int, std::string> MIS;
//-----1-----
template<typename T> const std::pair<int, std::string> mkpair1(T t)
{
static int i=0;
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(++i, ss.str());
}
template<typename...Any> void mkmap1(MIS &m, Any...any)
{
m = { mkpair1(any)... };
};
//-----2-----
template<typename T> const std::pair<int, std::string> mkpair2(int i, T t)
{
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(i, ss.str());
}
template<typename...Any> void mkmap2(MIS &m, Any...any)
{
static int i=0;
m = { mkpair2(++i, any)... };
};
//-----3-----
template<typename T> const std::pair<int, std::string> mkpair3(int &i, T t)
{
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(++i, ss.str());
}
template<typename...Any> void mkmap3(MIS &m, Any...any)
{
int i=0;
m = { mkpair3(i, any)... };
};
#endif
程序文件:
#include <iostream>
#include "test.h"
void ShowM(int x, const MIS &m)
{
std::cout << "\n---" << x << "---\n";
for (auto p:m) std::cout << p.first << " -> " << p.second << "\n";
}
int main(int argc, const char *argv[])
{
MIS m;
m.clear();
mkmap1(m, 1, "two", 3.1415, "four", 5);
ShowM(1, m);
m.clear();
mkmap2(m, 1, "two", 3.1415, "four", 5);
ShowM(2, m);
m.clear();
mkmap3(m, 1, "two", 3.1415, "four", 5);
ShowM(3, m);
return 0;
}
输出:
---1---
1 -> 1
2 -> four
---2---
1 -> 1
2 -> two
3 -> 3.1415
4 -> four
5 -> 5
---3---
1 -> 1
2 -> two
3 -> 3.1415
4 -> four
5 -> 5
为什么第一个模板函数无法正确构建地图?结果很奇怪。 (在 Linux 上使用 gcc)
编辑:
根据 cplusplus.com:
对“101010”的简洁解释
Because element keys in a map are unique, the insertion operation
checks whether each inserted element has a key equivalent to the one
of an element already in the container, and if so, the element is not
inserted, returning an iterator to this existing element (if the
function returns a value).
正如评论中@immibis正确提到的那样,由于模板参数推导,生成了3个模板函数mkpair1
的模板实例,即:
mkpair1<int>(...) // for inputs 1, 5
mkpair1<double>(...) // for input 3.1415
mkpair1<const char*>(...) // for input "tow" and "four"
因此,可变模板扩展看起来像:
m = { mkpair1<int>(1),
mkpair1<const char*>("two"),
mkpair1<double>(3.1415),
mkpair1<const char*>("four"),
mkpair1<int>(5)
};
现在,由于对于生成的每个模板实例,您还定义了不同的 static int i
,因此您将具有以下插入方案:
m.insert(std::make_pair(1, "1"); // OK
m.insert(std::make_pair(1, "two"); // ignored due to key 1 already exists
m.insert(std::make_pair(1, "3.1415"); // ignored due to key 1 already exists
m.insert(std::make_pair(2, "four"); // OK
m.insert(std::make_pair(2, "5")); // ignored due to key 2 already exists
因此,你得到的结果是正确的:
---1---
1 -> 1
2 -> four
头文件(test.h):
#ifndef _test_h_
#define _test_h_
#include <string>
#include <sstream>
#include <map>
typedef std::map<int, std::string> MIS;
//-----1-----
template<typename T> const std::pair<int, std::string> mkpair1(T t)
{
static int i=0;
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(++i, ss.str());
}
template<typename...Any> void mkmap1(MIS &m, Any...any)
{
m = { mkpair1(any)... };
};
//-----2-----
template<typename T> const std::pair<int, std::string> mkpair2(int i, T t)
{
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(i, ss.str());
}
template<typename...Any> void mkmap2(MIS &m, Any...any)
{
static int i=0;
m = { mkpair2(++i, any)... };
};
//-----3-----
template<typename T> const std::pair<int, std::string> mkpair3(int &i, T t)
{
std::stringstream ss;
ss << t;
return std::pair<int, std::string>(++i, ss.str());
}
template<typename...Any> void mkmap3(MIS &m, Any...any)
{
int i=0;
m = { mkpair3(i, any)... };
};
#endif
程序文件:
#include <iostream>
#include "test.h"
void ShowM(int x, const MIS &m)
{
std::cout << "\n---" << x << "---\n";
for (auto p:m) std::cout << p.first << " -> " << p.second << "\n";
}
int main(int argc, const char *argv[])
{
MIS m;
m.clear();
mkmap1(m, 1, "two", 3.1415, "four", 5);
ShowM(1, m);
m.clear();
mkmap2(m, 1, "two", 3.1415, "four", 5);
ShowM(2, m);
m.clear();
mkmap3(m, 1, "two", 3.1415, "four", 5);
ShowM(3, m);
return 0;
}
输出:
---1---
1 -> 1
2 -> four
---2---
1 -> 1
2 -> two
3 -> 3.1415
4 -> four
5 -> 5
---3---
1 -> 1
2 -> two
3 -> 3.1415
4 -> four
5 -> 5
为什么第一个模板函数无法正确构建地图?结果很奇怪。 (在 Linux 上使用 gcc)
编辑:
根据 cplusplus.com:
对“101010”的简洁解释Because element keys in a map are unique, the insertion operation checks whether each inserted element has a key equivalent to the one of an element already in the container, and if so, the element is not inserted, returning an iterator to this existing element (if the function returns a value).
正如评论中@immibis正确提到的那样,由于模板参数推导,生成了3个模板函数mkpair1
的模板实例,即:
mkpair1<int>(...) // for inputs 1, 5
mkpair1<double>(...) // for input 3.1415
mkpair1<const char*>(...) // for input "tow" and "four"
因此,可变模板扩展看起来像:
m = { mkpair1<int>(1),
mkpair1<const char*>("two"),
mkpair1<double>(3.1415),
mkpair1<const char*>("four"),
mkpair1<int>(5)
};
现在,由于对于生成的每个模板实例,您还定义了不同的 static int i
,因此您将具有以下插入方案:
m.insert(std::make_pair(1, "1"); // OK
m.insert(std::make_pair(1, "two"); // ignored due to key 1 already exists
m.insert(std::make_pair(1, "3.1415"); // ignored due to key 1 already exists
m.insert(std::make_pair(2, "four"); // OK
m.insert(std::make_pair(2, "5")); // ignored due to key 2 already exists
因此,你得到的结果是正确的:
---1---
1 -> 1
2 -> four