Проблема с типом возврата - PullRequest
1 голос
/ 10 ноября 2010

У меня есть классы:

    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);
            }
        }

    };

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

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

Ответы [ 2 ]

1 голос
/ 10 ноября 2010

Я вижу, что вы используете 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 голосов
/ 10 ноября 2010

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

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

...