@Acaunt

Почему явная специализация невозможна?

У меня есть следующий класс (убрал всё лишнее здесь, потому что не даёт полностью сюда написать) :
Text_File.h
#ifndef TEXT_FILE_H

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <filesystem>

class Text_File {
public:
	Text_File(const std::string &directory, const std::string &name_file, const std::vector<std::vector<std::string>> &list_parameters)
		: directory_(directory), name_file_(name_file), list_parameters_(list_parameters) {};
	std::vector<std::vector<std::string>> text_from_file;
	template <typename T>
	T search(std::string parameter);
	template <typename T>
	T rewrite(std::string parameter, std::string value = "");
	/*
	template <>
	std::string rewrite(std::string parameter, std::string value);
	template <>
	int rewrite(std::string parameter, std::string value);
	template <>
	float rewrite(std::string parameter, std::string value);
	template <>
	double rewrite(std::string parameter, std::string value);
	template <>
	bool rewrite(std::string parameter, std::string value);
	template <>
	char rewrite(std::string parameter, std::string value);
	*/
private:
	std::vector<std::vector<std::string>> list_parameters_{};
	std::string directory_{};
	std::string name_file_{};
	std::string get_standard_value(std::string parameter);
	template <typename T>
	bool check_type(const std::string &value);
};

#endif // !TEXT_FILE_H

и его реализация:
Text_File.cpp
#include "Text_File.h"

template <>
std::string Text_File::search(std::string parameter) {
	std::cout << "Search in file -> " << name_file_ << " -> parameter -> " << parameter << std::endl;

	for (std::vector<std::string>& text : text_from_file) {
		if (text[0] == parameter) {
			if (text[1] != "") {
				std::cout << parameter << " " << text[1] << std::endl;
				return text[1];
			}
			break;
		}
	}
	
	std::cout << "Not found parametr -> " << parameter << std::endl;

	return rewrite<std::string>(parameter);
}

template <>
int Text_File::search(std::string parameter) {
	std::string value = search<std::string>(parameter);

	if (!check_type<int>(value)) { return rewrite<int>(parameter); }

	return stoi(value);
}

template <>
float Text_File::search(std::string parameter) {
	std::string value = search<std::string>(parameter);

	if (!check_type<float>(value)) { return rewrite<float>(parameter); }

	return stof(value);
}

template <>
double Text_File::search(std::string parameter) {
	std::string value = search<std::string>(parameter);

	if (!check_type<double>(value)) { return rewrite<double>(parameter); }

	return stod(value);
}

template <>
bool Text_File::search(std::string parameter) {
	std::string value = search<std::string>(parameter);

	if (!check_type<bool>(value)) { return rewrite<bool>(parameter); }

	return stoi(value);
}

template <>
char Text_File::search(std::string parameter) {
	std::string value = search<std::string>(parameter);

	if (!check_type<char>(value)) { return rewrite<char>(parameter); }

	return value[0];
}

template <>
std::string Text_File::rewrite(std::string parameter, std::string value) {
	std::cout << "Rewrite in file -> " << name_file_ << " -> parameter -> " << parameter;

	if (value == "") {
		std::cout << std::endl;
		value = get_standard_value(parameter);
		if (value == "") { return ""; }
	}
	else {
		std::cout << " " << value << std::endl;
	}

	rename((directory_ + name_file_).c_str(), (directory_ + "Copy.txt").c_str());

	read.open(directory_ + "Copy.txt");
	write.open(directory_ + name_file_);

	if (!read.is_open() || !write.is_open()) {
		read.close();
		write.close();
		remove((directory_ + name_file_).c_str());
		rename((directory_ + "Copy.txt").c_str(), (directory_ + name_file_).c_str());
		std::cout << "Fail rewrite in file -> " << name_file_ << std::endl;
		return "";
	}

	while (!read.eof()) {
		std::string text;
		getline(read, text);

		if (text.substr(0, text.find(" ")) == parameter) {
			write << parameter << " " << value << std::endl;
		}
		write << text << std::endl;
	}

	for (std::vector<std::string> &text : text_from_file) {
		if (text[0] == parameter) {
			text[1] = value;
		}
	}

	return value;
}

template <>
int Text_File::rewrite(std::string parameter, std::string value) {
	value = rewrite<std::string>(parameter, value);

	if (!check_type<int>(value)) { return 0; }

	return stoi(value);
}

template <>
float Text_File::rewrite(std::string parameter, std::string value) {
	value = rewrite<std::string>(parameter, value);

	if (!check_type<float>(value)) { return 0; }

	return stof(value);
}

template <>
double Text_File::rewrite(std::string parameter, std::string value) {
	value = rewrite<std::string>(parameter, value);

	if (!check_type<double>(value)) { return 0; }

	return stof(value);
}

template <>
bool Text_File::rewrite(std::string parameter, std::string value) {
	value = rewrite<std::string>(parameter, value);

	if (!check_type<bool>(value)) { return false; }

	if (value == "1" || value == "true" || value == "TRUE") { return true; }

	return false;
}

template <>
char Text_File::rewrite(std::string parameter, std::string value) {
	value = rewrite<std::string>(parameter, value);

	if (!check_type<double>(value)) { return char{}; }

	return value[0];
}

std::string Text_File::get_standard_value(std::string parameter) {
	std::cout << "Get standard value parameter -> " << parameter << std::endl;

	for (std::vector<std::string>& text : list_parameters_) {
		if (text[0] == parameter) {
			std::cout << parameter << " " << text[1] << std::endl;
			return text[1];
		}
	}

	std::cout << std::endl << parameter << " -> not exit" << std::endl;
	
	return "";
}

template<typename T>
bool Text_File::check_type(const std::string& value) {
	if (value == "") {
		std::cout << "Not correct value -> \"" << value << "\"" << std::endl;
		return false;
	}

	T result();

	if constexpr (std::is_same<T, std::string>::value) { return true; }
	else if constexpr (std::is_same<T, int>::value) {
		char* end;
		strtol(value.c_str(), &end, 10);
		if (!*end) { return true; }
	}
	else if constexpr (std::is_same<T, float>::value) {
		char* end;
		strtof(value.c_str(), &end);
		if (!*end) { return true; }
	}
	else if constexpr (std::is_same<T, double>::value) {
		char* end;
		strtod(value.c_str(), &end);
		if (!*end) { return true; }
	}
	else if constexpr (std::is_same<T, bool>::value) {
		if (value == "1" || value == "true"  || value == "TRUE" ||
			value == "0" || value == "false" || value == "FALSE") { return false; }
	}
	else if constexpr (std::is_same<T, char>::value) {
		if (value.length() == 1) { return true; }
	}
	
	std::cout << "Not correct value -> \"" << value << "\"" << std::endl;

	return false;
}

В этом классе есть две шаблонные функции:
search;
rewrite;
Но почему то только rewrite выдаёт следующие ошибки:
Явная специализация; уже создан экземпляр " T Text_File::rewrite(std::string, std::string)"
Text_File::rewrite явная специализация невозможна
И так несколько раз для других типов.
Но если я пропишу в самом классе для всех типов то ошибки не будет (в том коде что отправил я закомментировал эти строчки).
Вопрос: Почему?
  • Вопрос задан
  • 161 просмотр
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
Проблема вызвана использованием шаблона rewrite из шаблона search.

Если вы перенесете специализацию шаблона rewrite вверх, до специализации search, то все скомпилируется. Или надо где-то выше первого использования шаблона rewrite задекларировать специализацию (что ваш закомментированный код и делает).

Вызвана эта ошибка стандартом.
Надо, чтобы специализация шаблона была задекларирована до любого использования:
Specialization must be declared before the first use that would cause implicit instantiation, in every translation unit where such use occurs:
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы