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

时间:2016-01-16 11:08:39

标签: c++ variadic-templates static-variables

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

编辑:

关注&#39; 101010&#39;整洁的解释,来自cplusplus.com

  

因为地图中的元素键是唯一的,所以插入操作   检查每个插入的元素是否具有与该元素等效的键   已经在容器中的元素,如果是,则元素不是   插入,将迭代器返回到此现有元素(如果是   函数返回一个值。)

1 个答案:

答案 0 :(得分:2)

正如评论中提到的@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