Доступ к типу результата параметра шаблона функции в шаблоне? - PullRequest
2 голосов
/ 18 августа 2010

Учитывая следующий шаблон:

template<class T>
class Container
{
private:

    boost::function<T> f;
};

... и его создание, возможно, следующим образом:


    Container<bool(int, int)> myContainer;

, есть ли способ получить доступ к типу возврата функцииописание и составить условно против этого?Например, если вызывающая сторона указывает, что его функция возвращает bool (как в приведенном выше случае), я хочу включить функцию, которая возвращает значение.Если он указывает, что функция void, я не хочу, чтобы эта функция была включена.Например:


// Include if the return type of T is void
template<class T1, class T2>
void DoSomething(T1 t1, T2 t2)
{
    f(t1, t2);
}

// Include if the return type of T is not void
template<class T1, class T2>
***whatever the return type is*** DoSomething(T1 t1, T2 t2)
{
    return f(t1, t2);
}

Я предполагаю, что здесь есть решение, но оно, вероятно, включает какое-то ужасно запутанное решение для метапрограммирования шаблонов.Я знаю, что Грегор Кантор сошел с ума, созерцая бесконечность ... шаблонное метапрограммирование оказывает на меня такое же влияние: стр.

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

RobinsonT

Редактировать: Очевидно, что это можно решить путем реализации другого класса (возможно, полученного из общей базы), один с именем VoidContainer, а другой с именем ReturnsContainer (или аналогичный).Однако мне это кажется немного неудовлетворительным ...

Ответы [ 3 ]

3 голосов
/ 18 августа 2010

Я не думаю, что вам действительно нужно специализироваться на пустом типе возврата.Функция void может возвращать «результат» другой функции void именно для этого сценария.

void foo() { }
void bar() { return foo(); } //this is OK

int main()
{
    bar();
}

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

Похожечто boost::function имеет typedef для result_type (см. http://beta.boost.org/doc/libs/1_37_0/doc/html/boost/functionN.html)

#include <boost/function.hpp>


template<class T>
class Container
{
public:
    typedef typename boost::function<T>::result_type result_type;
private:

    boost::function<T> f;
};

Container<bool(int, int)>::result_type r = true;

Редактировать: Теперь, когда вы знаете, что такое result_type, и вам нужно различать void /не пустые результаты, вы можете использовать enable_if и disable_if. Единственная сложность заключается в том, что они работают только с шаблонами функций, поэтому не шаблон foo вызывает шаблонный do_foo.

#include <boost/function.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
#include <cstdio>

template<class T>
class Container
{
public:
    typedef typename boost::function<T>::result_type result_type;


    result_type foo() 
    {
        return do_foo<result_type>();
        //note that this still works because you can return the void result! :)
    }
private:
    //use this if the result_type is void
    template <class U>
    typename boost::enable_if<boost::is_same<U, void>, U >::type do_foo()
    {
        std::puts("for void");
    }

    //else
    template <class U>
    typename boost::disable_if<boost::is_same<U, void>, U>::type do_foo()
    {
        std::puts("other");
        return U();
    }
private:

    boost::function<T> f;
};


int main()
{
    Container<void()> a;
    a.foo();

    Container<int()> b;
    b.foo();
}
3 голосов
/ 18 августа 2010

Да, вы можете использовать boost::function_traits, который имеет result_type typedef.

0 голосов
/ 18 августа 2010

В зависимости от того, что вы хотите, возможно, вы делаете вещи более сложными, чем необходимо.Если f, который вы вызываете в случае void, является самой функцией void, вы можете просто оставить return.

Явным образом возвращать «значение void» - все в порядке:

void f() {
}

void g() {
   return f();
}
...