Я работаю над базой кода, где C ++ API собирается измениться (основная ветвь и функциональная ветвь), и я хочу защитить свой код от изменений, чтобы мой код создавался для обеих версий. Как минимальный рабочий пример godbolt / ссылка компилятора-проводника :
общая:
class SmallWidget {
private:
int m_i;
public:
int i() { return m_i; }
};
мастер:
class BigWidget {
private:
std::vector<SmallWidget*> m_v;
public:
auto& widgets() { return m_v; }
};
ветвь функции:
class BigWidget {
private:
std::vector<SmallWidget> m_v;
public:
auto& widgets() { return m_v; }
};
/**/
Для мастер-версии у меня есть код вызова:
int single_op(BigWidget& w) {
return (*w.widgets().begin())->i(); // asterisk will need to go
}
std::vector<int> do_stuff(std::vector<BigWidget> inputs) {
std::vector<int> retval;
for (auto w : inputs) {
retval.push_back(single_op(w));
}
return retval;
}
API не поставляется с переменной препроцессора для выбора с помощью
#if WIDGET_VERSION == OLD
return (*w.widgets().begin())->i(); // asterisk will need to go
#else
return (w.widgets().begin())->i(); // asterisk gone
#endif
Я пытался определить тип возвращаемого значения widgets
с помощью sfinae:
// version for the master branch API
template <typename = typename std::enable_if<std::is_same<
std::remove_const<std::remove_reference<decltype(**(
std::declval<BigWidget>().widgets().begin()))>::type>::type,
SmallWidget>::value>::type>
int single_op(BigWidget& w) {
return (*w.widgets().begin())->i();
}
// version for the feature branch API
template <typename = typename std::enable_if<std::is_same<
std::remove_const<std::remove_reference<decltype(*(
std::declval<BigWidget>().widgets().begin()))>::type>::type,
SmallWidget>::value>::type>
int single_op(BigWidget& w) { return w.widgets().begin()->i(); }
Но компиляторы этому не рады. лязг говорит:
<source>:43:46: error: failed requirement 'std::is_same<std::remove_const<std::remove_reference<decltype(* (std::declval<BigWidget>().widgets().begin()))>::type>::type, SmallWidget>::value'; 'enable_if' cannot be used to disable this declaration
шаблон
Есть ли способ использовать sfinae для включения правильного кода здесь?
Я также пытался использовать std::enable_if
для кода возврата или аргументов функции, но, насколько я понимаю, компилятор всегда видит сигнатуру int single_op(BigWidget&)
для обеих версий.