В качестве упражнения я разрабатываю ориентированный на цель планировщик действий в Unreal Engine 4. Я пытаюсь настроить свои собственные структуры, которые я могу использовать для динамического описания состояния мира, используя список данных переменной длины, состоящий из отдельных типов переменных. Я думал, что вариативные шаблонные структуры могут быть интересным способом сделать это, но при реализации метода доступа к значению я столкнулся с проблемами.
Я хочу, чтобы он работал, чтобы я мог создавать экземпляры этих структур во время выполнения, используя FDataKeys<T>
в общих параметрах для FFact<T...>
. Затем я хочу иметь функцию GetValue<S>(string Key)
, которая будет рекурсивно проверять ключи данных, пока не будет найдено совпадение. Я буду реализовывать параметр флага, чтобы указать на успех или неудачу поиска, но я получаю ошибку компиляции в моем рабочем коде, которая не имеет для меня смысла.
Я знаю, что могу настроить вспомогательный класс со статической функцией для этого, но мне любопытно, почему это не работает и как я смогу реализовать это таким образом, если это возможно.
Сообщение об ошибке:
38:42: предупреждение: ISO C ++ запрещает использование ‘auto’ в объявлении параметра [-Wpedantic] При создании экземпляра ‘S FFact ‹T, R …› :: GetValue (const string &) [with S = char; Т = std :: basic_string; R = {}; std :: string = std :: basic_string] ‘:
50:45: требуется рекурсивно из ‘S FFact ‹T, R …› :: GetValue (const string &) [with S = char; Т = логический; R = {std :: basic_string ‹char, std :: char_traits, std :: allocator›}; std :: string = std :: basic_string] ‘
50:45: требуется от ‘S FFact ‹T, R …› :: GetValue (const string &) [with S = char; T = char; R = {bool, std :: basic_string ‹char, std :: char_traits, std :: allocator›}; std :: string = std :: basic_string] ‘
67:37: требуется отсюда
46:25: ошибка: невозможно преобразовать ‘std :: basic_string’ в ‘char’ в возвращении В функции-члене ‘S FFact ‹T, R …› :: GetValue (const string &) [with S = char; Т = std :: basic_string; R = {}; std :: string = std :: basic_string] ‘:
52: 5: предупреждение: элемент управления достигает конца непустой функции [-Wreturn-type]
Код:
// FFact struct experiments
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Key-Value data struct
template<typename T>
struct FDataKey
{
FDataKey(string KeyStr, T Data)
{
Key = KeyStr;
Value = Data;
}
string Key;
T Value;
};
// Basic struct to enable generic recursion
template<typename ... T>
struct FFact
{
// GetValue's bottom of the barrel
// ToDo: Implement check that Key was not found
template<typename S>
S GetValue(string Key)
{
S defaultValue;
return defaultValue;
}
};
// Variadic templated container meant for FDataKey<> types only
template<typename T, typename ... R>
struct FFact<T, R...>
{
// Constructors
FFact(){}
FFact(const FDataKey<T>& FirstValue, const auto& ...Rest) : Data(FirstValue), Remainder(Rest...)
{}
// Recursively check Data members for FDataKeys with matching keys
template<typename S>
S GetValue(const string& Key)
{
if(Data.Key == Key)
{
return Data.Value;
}
else
{
return Remainder.GetValue<S>(Key);
}
}
// Member variables
FDataKey<T> Data;
FFact<R...> Remainder;
};
// Run tests
int main()
{
// Setup testing Fact
FFact<char, bool, string> f = FFact<char,bool,string>(
FDataKey<char>("Initial", 'w'),
FDataKey<bool>("Cake",false),
FDataKey<string>("Marco","Polo")
);
cout << f.GetValue<char>("Initial") << endl;
cout << f.GetValue<bool>("Cake") << endl;
cout << f.GetValue<string>("Marco") << endl;
}
return Data.Value;
— вы делаете return Data.Value;
из каждого рекурсивного вызова, даже когда вы возвращаете S
. Бывший. в GetValue<char>
. C ++ статически типизирован, тогда каждый Data.Value
должен быть преобразован в char
. — person LazarusOfSuburbia schedule 21.02.2021
Думаю, вот что меня смущает. Поскольку Data.Value
не следует возвращать до тех пор, пока ключ не совпадет. Таким образом, единственным преобразованием типа должно быть преобразование S в typeof(Data.Value)
, которое должно выдавать ошибку только тогда, когда в вызове передаются неправильные универсальные типы. — person LazarusOfSuburbia schedule 21.02.2021
should not be returned
он не будет возвращен, но статически все пути должны быть действительными. Как int func() { if (0) { return std::string{}; } return 5; }
не будет компилироваться, независимо от того, что строка никогда не возвращается. — person LazarusOfSuburbia schedule 21.02.2021
Вот и все, он компилируется: