Если Вы никогда не планируете взаимодействовать с репозиторием, из которого Вы клонировались, можно сделать полное клон мерзавца и переписать репозиторий с помощью ответвление фильтра мерзавца - фильтр подкаталога . Таким образом, по крайней мере, история будет сохранена.
Я нашел ОЧЕНЬ простое решение!
class Base
{
};
class Derived : public Base
{
};
class Different
{
};
class X
{
private:
template <typename T>
static const char *intFunc(const void *, T *data)
{
// Do something generic...
return "Generic";
}
template <typename T>
static const char *intFunc(const Base *, T *data)
{
// Do something specific...
return "Specific";
}
public:
template <typename T>
static const char *func(T *data)
{
return intFunc(data, data);
}
};
Он отлично работает и очень тонкий! Уловка состоит в том, чтобы позволить компилятору выбрать правильный метод с помощью (в противном случае бесполезного) первого параметра.
Для этого необходимо использовать SFINAE . В следующем коде первая функция может быть создана тогда и только тогда, когда вы передаете что-то, что не может быть (неявно) преобразовано в Base *
. Вторая функция имеет обратное.
Вы можете прочитать enable_if
.
#include <iostream>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
class Base {};
class Derived : public Base {};
class Different {};
struct X
{
template <typename T>
static typename boost::disable_if<boost::is_convertible<T *, Base *>,
const char *>::type func(T *data)
{
return "Generic";
}
template <typename T>
static typename boost::enable_if<boost::is_convertible<T *, Base *>,
const char *>::type func(T *data)
{
return "Specific";
}
};
int main()
{
Derived derived;
Different different;
std::cout << "Derived: " << X::func(&derived) << std::endl;
std::cout << "Different: " << X::func(&different) << std::endl;
}
Если вы используете ускорение, вы можете сделать это с помощью некоторого метапрограммирования шаблона:
#include <boost/type_traits/is_base_of.hpp>
class X
{
private:
template <typename T>
static const char *generic_func(T *data)
{
// Do something generic...
return "Generic";
}
template <typename T>
static const char *base_func(T *data)
{
// Do something specific...
return "Specific";
}
public:
template <typename T>
static const char* func(T* data)
{
if (boost::is_base_of<Base, T>::value)
return base_func(data);
return generic_func(data);
}
};
Метафункция is_base_of
оценивается во время компиляции, и оптимизатор, скорее всего, удалит мертвая ветвь if
в функции func
. Такой подход позволяет иметь более одного конкретного случая.
Выражение:
X::func(derived)
Означает, что компилятор сгенерирует объявление и код, который фактически имеет эту сигнатуру:
static const char *func(Derived *data);
, которая оказывается более подходящей, чем ваша:
static const char *func(Base *data);
Функция шаблона будет использоваться для всего, что допустимо для typename, например, для любого класса, который вы используете как T, и он будет эффективно исключать использование Base
версии вашей функции из-за политики времени компиляции.
Я предлагаю использовать специализация в X для ваших конкретных типов, например:
template <typename T>
static const char *func(T *data)
{
// Do something generic...
return "Generic";
}
template <>
static const char *func(Derived *data) // 'Derived' is the specific type
{
// Do something specific...
return "Specific";
}
Надеюсь, что это сработает!
Просто приведение типов, производное от base
X :: func ((Base *) & производное)
работает ....