模板函数中的静态变量失败

Static variable in template function fail

本文关键字:静态 变量 失败 函数      更新时间:2023-10-16

头文件 (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)

编辑:

在"101010"简洁的解释之后,来自 cplusplus.com:

由于映射中的元素键是唯一的,因此插入操作 检查每个插入元素是否具有与该元素等效的键 容器中已有的元素,如果是,则该元素不是 插入,返回此现有元素的迭代器(如果 函数返回一个值)。

正如注释中正确@immibis提到的,由于模板参数推导,mkpair1生成了 3 个模板函数的模板实例化,即:

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