Перегрузки членов C ++, основанные на существовании члена шаблона - PullRequest
0 голосов
/ 22 мая 2018

Я начинал с какого-то SFINAE, но не совсем понимаю, в каких случаях я хочу его использовать.

Например, если у меня есть класс на основе шаблона, который должен иметь различные реализации функции в зависимости от параметра шаблона, например

template <typename T>
class cExampleClass
{
     /// Function enabled when "cExampleClass::member" exists
     auto overloadedFunction() -> decltype((std::declval<t>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     auto overloadedFunction() -> T::some_dependant_type()
     {
           // Do some different stuff
     }
};

, где было бы идеально просто вызвать функцию как

object.overloadedFunction();

Мой компилятор выдает

ошибка: в 'class cARD' нет члена с именем 'member'

в строке decltype (даже когдафункция отката не определена).Это кажется противоречащим ответу здесь , так как правильно определить тип конечного возврата?

Кроме того, функция, очевидно, не может быть перегружена.Есть ли простой способ определить запасную функцию?

1 Ответ

0 голосов
/ 22 мая 2018

У вас серьезная ошибка, поскольку ваш метод не является шаблоном, замените его на:

template <typename U>
class cExampleClass
{
     /// Function enabled when "cExampleClass::member" exists
     template <typename T = U>
     auto overloadedFunction()
     -> decltype((std::declval<T>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     template <typename T = U>
     auto overloadedFunction() -> decltype(T::some_dependant_type())
     {
           // Do some different stuff
     }
};

, но у вас возникнет проблема, поскольку метод будет неоднозначным для типа, соответствующего обоим условиям.

Добавление тега для сортировки перегрузок возможно:

template <std::size_t I>
struct overload_tag : overload_tag<I - 1> {};

template <>
struct overload_tag<0> {};

, а затем

template <typename U>
class cExampleClass
{
private:
     /// Function enabled when "cExampleClass::member" exists
     /// Preferred function
     template <typename T = U>
     auto overloadedFunction(overload_tag<1>)
     -> decltype((std::declval<T>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     template <typename T = U>
     auto overloadedFunction(overload_tag<0>) -> decltype(T::some_dependant_type())
     {
           // Do some different stuff
     }
public:
     template <typename T = U>
     auto overloadedFunction() -> decltype(overloadedFunction(overload_tag<1>{}))
     {
          return overloadedFunction(overload_tag<1>{});
     }
};
...