2010-11-10 3 views
1

У меня есть классы:Проблема с возвращаемым типом

struct Policy_1 
    { 
     void signalFailure() 
     { 
      throw std::exception(); 
     } 
    }; 

    struct Policy_2 
    { 
     void* signalFailure() 
     { 
      return nullptr; 
     } 
    }; 

    template<class Policy> 
    struct My 
    {  
     template<class T> 
     T* fnc(int value) 
     { 
      if (!value) 
      { 
       return Policy::signalFailure();//Here is the problem 
      } 
      else 
      { 
       return new int(value); 
      } 
     } 

    }; 

Проблема заключается в том, что в зависимости от политики класса signalFailure либо бросает или возвращает nullptr, но я получаю сообщение об ошибке от компилятора (даже если политика установлено, что он делает бросить), что он не может преобразовать void в (T *) - в зависимости от того, что я заменил чаем; Теперь я понимаю, в чем проблема: компилятор проверяет синтаксис и обнаруживает, что из этой Политики signalFailure возвращает void, поэтому он не может разобрать его, даже если signalFailure на практике бросает.

У меня есть два варианта, как я вижу это:
а) либо объявить недействительным * в качестве типа результата signalFailure
б) объявить недействительным как тип результата в FNC и переместить тип результата в списке аргументов этого fnc или
c) сделайте макрос или метапрограммирование внутри моего fnc (и вот вам реальное Q), которое будет определено во время компиляции (либо вернуть политику :: etc, либо просто Policy :: и т. д.), и что я думаю будет лучшим вариантом. Конечно, если кто-то из вас имеет лучшую и более элегантную идею, как это сделать, более чем можно его показать.

+1

Не должен ли 'signalFailure()' быть статическим? – sharptooth

+0

@sharptooth Я согласен, хотя я ожидаю, что в реальном коде он создает сообщение об исключении из Policy_1 – Rup

ответ

1

Я вижу, что вы используете nullptr-, что означает, что вы должны быть в C++ 0x. В этом случае тривиально использовать decltype для решения этой проблемы.

template<class Policy> 
struct My 
{ 
    template<typename T> struct func_helper { 
     static T func() { return Policy::signalFailure(); } 
    };  
    template<> struct func_helper<void> { 
     static void* func() { Policy::signalFailure(); return nullptr; } 
    }; 
    template<class T> 
    T* fnc(int value) 
    { 
     if (!value) 
     { 
      return func_helper<decltype(Policy::signalFailure())>::func(); 
     } 
     else 
     { 
      return new int(value); // Compile error if int* cannot be converted 
            // to the type of the policy. 
     } 
    } 

}; 

Редактировать: Подождите секунду. Этот код СЕРЬЕЗНО неправильно. Вы возвращаете новый int(), как T *? Этот код не нуждается в исправлении, ему нужен весь модуль.

+0

nullptr является частью C++ CLI до C++ 0x – Motti

+0

, но тогда второй возврат будет недействительным, если signalFailure вернет void. –

+0

@There: Это хороший момент. Мне нужно будет отредактировать мой ответ. – Puppy

0

Я не был бы шокирован, если бы политика бросания имела возвращаемую стоимость, хотя и не использовалась, и это, вероятно, то, что я сделал бы. Однако, если вы не избежите void *, вы также можете сделать шаблон методов signalFailure и позвонить по телефону Policy::signalFailure<T>() из fnc (таким образом, чтобы методы signalFailure вернули более строго типизированный T *).

На стороне примечания методы signalFailure должны быть либо статическими, либо My должны в частном порядке наследоваться от вашего класса Policy.

Смежные вопросы