не удалось вывести параметр шаблона

Я пытаюсь использовать API, который похож на следующее:

#include<iostream>
#include<boost/optional.hpp>

class Base
{
int id;
public:
int get_id()
{
return id;
}
};

class A : public Base
{
};

class B : public Base
{
};

class M
{
public:
enum Type
{
t_A,
t_B
};
Type type;
boost::optional<A&> a;
boost::optional<B&> b;
boost::optional<A&> get_A()
{
return a;
}

boost::optional<B&> get_B()
{
return b;
}

};

Мне нужно добраться до базы через любой производный класс. Итак, я создал шаблонную функцию, как это:

template<class T>
boost::optional<T&> get(M & m)
{
switch(m.type)
{
case M::t_A :
return m.get_A();
case M::t_B :
return m.get_B();
default:
throw;
};
}

int main()
{
M m;
//... initialization of m
int i = get<>(m)->get_id();
return 0;
}

но аргумент шаблона моей функции не может быть выведен:

template_sp_1.cpp:63:17: error: no matching function for call to ‘get(M&)’
int i = get<>(m)->get_id();
^
template_sp_1.cpp:63:17: note: candidate is:
template_sp_1.cpp:46:21: note: template<class T> boost::optional<T&> get(M&)
boost::optional<T&> get(M & m)
^
template_sp_1.cpp:46:21: note:   template argument deduction/substitution failed:
template_sp_1.cpp:63:17: note:   couldn't deduce template parameter ‘T’
int i = get<>(m)->get_id();

попытка любого из следующего невозможна; по-видимому, из-за использования boost::optional :

int i = get<Base>(m)->get_id();
int i = get<A>(m)->get_id();
int i = get<B>(m)->get_id();

У вас есть решение для таких сценариев? (Я не могу прикоснуться к API)

2

Решение

Как уже указывал @ Manu343726, ваш get() Функция имеет различные типы возвращаемых данных. Но с тех пор A а также B иметь общий базовый класс Baseпочему вы не используете тип возврата Base&?

Eсть ошибка в boost::optional относительно ссылок, которые были исправлены в boost 1.58, так что вам нужна хотя бы эта версия.
Я изменил ваш пример, чтобы показать, как он может работать:

#include <boost/optional.hpp>
#include <boost/version.hpp>
#include <iostream>#if BOOST_VERSION < 105800
#error boost version must be at least 1.58
#endif

class Base
{
int id;
public:
Base(int id) : id(id) {}
int get_id()
{
return id;
}
};

class A : public Base
{
public:
A() : Base(100) {}
};

class B : public Base
{
public:
B() : Base(999) {}
};

class M
{
public:
enum Type
{
t_A,
t_B
};
Type type;
boost::optional<A&> a;
boost::optional<B&> b;
boost::optional<A&> get_A()
{
return a;
}

boost::optional<B&> get_B()
{
return b;
}

};Base& get(M & m)
{
switch(m.type)
{
case M::t_A :
return (*(m.get_A()));
case M::t_B :
return (*(m.get_B()));
default:
throw;
};
}

int main()
{
A a;
M m;
m.type = M::t_A;
m.a = a;
Base& base = get(m);
std::cout << base.get_id() << std::endl;
return 0;
}

Этот пример выведет:

100

Это, конечно, работает только во время выполнения, если API гарантирует, что get_A() или же get_B() вернуть необязательный, содержащий действительную ссылку.
Если это не гарантировано, вы можете использовать что-то вроде этого:

boost::optional<Base&> get(M & m)
{
boost::optional<Base&> base;
switch(m.type)
{
case M::t_A:
base = m.get_A();
break;
case M::t_B :
base = m.get_B();
break;
default:
throw;
};
return base;
}
1

Другие решения

Ошибка компилятора довольно очевидна: поскольку T не зависит от какого-либо параметра функции, и вы не передаете его явно, компилятору не удалось вывести значение для T.

Обратите внимание, что эти опции a и b имеют разные типы, поэтому ваша функция get () пытается вернуть несколько разных типов (следовательно, вы пытаетесь использовать шаблонную опцию?)

C ++ не работает таким образом, так как тип должен быть определен во время компиляции, и ваше решение зависит от значения времени выполнения (переключение). Подумайте о возврате типа варианта, такого как boost :: option.

2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector