2

次のテンプレートがあるとします。

テンプレート<クラス T>
クラスコンテナ
{
プライベート:

    boost::function<T> f;
};

... およびそのインスタンス化は、おそらく次のようになります。


    Container<bool(int, int)> myContainer;

、関数記述の戻り値の型にアクセスし、それに対して条件付きでコンパイルする方法はありますか? たとえば、呼び出し元が自分の関数が bool を返すように指定した場合 (上記の場合のように)、値を返す関数を含めたいと思います。彼が関数が無効であると指定した場合、この関数を含めたくありません。例えば:


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

ここに解決策があると思いますが、おそらく、恐ろしく難読化されたテンプレート メタプログラミング ソリューションが関係しています。Gregor Cantor が無限を考えて発狂したことは知っています... テンプレートのメタプログラミングのようなものは、私にも同じ影響を与えます :p.

ご意見ありがとうございます。

ロビンソンT

編集: 明らかに、これは別のクラス (おそらく共通のベースから派生) を実装することで解決できます。1 つは VoidContainer と呼ばれ、もう 1 つは ReturnsContainer (または類似) と呼ばれます。しかし、これは私には少し物足りないようです...

4

3 に答える 3

3

実際に void 戻り型に特化する必要はないと思います。void 関数は、まさにこのシナリオで別の void 関数の「結果」を返すことができます。

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

int main()
{
    bar();
}

したがって、唯一の問題は、戻り値の型を決定する方法です。

boost::functionのtypedefがあるようです(result_typehttp://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、無効/非無効の結果を区別する必要があるため、 と を使用でき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();
}
于 2010-08-18T17:02:53.093 に答える
3

はい、typedefboost::function_traitsを持つ を使用できます。result_type

于 2010-08-18T16:51:32.900 に答える
0

やりたいことによっては、必要以上に複雑にしている可能性があります。fケースで呼び出す が void 関数自体である場合voidは、そのままにしておくことができますreturn

「void 値」を明示的に返すことは問題ありません。

void f() {
}

void g() {
   return f();
}
于 2010-08-18T17:00:36.067 に答える