Шаблонная функция и static переменная
Подскажите пожалуйста, а как нужно правильно реализовать static переменную в шаблонной функции ?
Ну то есть вот так, как с обычной функцией нельзя: компилятор ругается на переопределение переменной my_int:
static int my_int;
template <typename char_wchar_type>
int my_func_shablon_1(char_wchar_type* my_char_p)
{
//.....
return 0;
}
.
static int my_int;
template <typename string_wstring_type>
int my_func_shablon_2(string_wstring_type my_string)
{
//.....
return 0;
}
.
#include "my_func_shablon_1.h"
#include "my_func_shablon_2.h"
int main()
{
}
А как тогда можно сделать static переменную для конкретного .h - файла ? Или это невозможно ?
Ответы (2 шт):
Неважно в каком файле вы объявляете переменную. Препроцессор просто вставляет текст из файлов .h в файл с функцией main(). И получается двойное объявление переменной.
Можно использовать директивы препроцессора
#ifndef MY_INT
#define MY_INT
static int my_int=0;
#endif
Но проще обе функции описать в одном .h-файле
Поместите статическую переменную в шаблон. Компилятор и компоновщик гарантируют что дублирующиеся определения этой переменной будут объединены вместе.
t.hpp:
#ifndef T_HPP_
#define T_HPP_
template <typename T_> struct T {
static T_ v;
};
template <typename T_> T_ T<T_>::v;
#endif // #ifndef T_HPP_
Два правила:
Во всех единицах трансляции
T<int>::vссылается на одну и ту же переменную.T<int>::vиT<double>::vссылаются на две разные переменные.
Демонстрация:
m1.hpp:
#ifndef M1_HPP_
#define M1_HPP_
namespace m1 {
int get_int ();
double get_double();
void add_int (int v);
void add_double(double v);
} // namespace m1
#endif // #ifndef M1_HPP_
m2.hpp:
#ifndef M2_HPP_
#define M2_HPP_
namespace m2 {
int get_int ();
double get_double();
void add_int (int v);
void add_double(double v);
} // namespace m2
#endif // #ifndef M2_HPP_
m1.cpp:
#include <m1.hpp>
#include <t.hpp>
namespace m1 {
int get_int () { return T<int >::v; }
double get_double() { return T<double>::v; }
void add_int (int v) { T<int >::v += v; }
void add_double(double v) { T<double>::v += v; }
} // namespace m1
m2.cpp:
#include <m2.hpp>
#include <t.hpp>
namespace m2 {
int get_int () { return T<int >::v; }
double get_double() { return T<double>::v; }
void add_int (int v) { T<int >::v += v; }
void add_double(double v) { T<double>::v += v; }
} // namespace m2
main.cpp:
#include <iostream>
#include <m1.hpp>
#include <m2.hpp>
int main() {
std::cout << m2::get_int() << ' ' << m2::get_double() << '\n';
m1::add_int(2);
m1::add_double(3);
std::cout << m2::get_int() << ' ' << m2::get_double() << '\n';
}
$ g++ -std=c++17 -pedantic -Wall -Wextra -Werror -I. main.cpp m1.cpp m2.cpp $ ./a.out 0 0 2 3
Модули m1 и m2 делят общее состояние, целиком описанное в заголовке t.hpp.