在模板中访问函数模板参数的结果类型?

发布于 2024-09-14 18:22:56 字数 899 浏览 12 评论 0原文

给定以下模板:

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

我猜这里有一个解决方案,但它可能涉及一些极其混乱的模板元编程解决方案。我知道格雷戈尔·康托 (Gregor Cantor) 疯狂地思考着无穷大……模板元编程对我也有同样的效果:p。

感谢您的任何想法。

RobinsonT

编辑:显然,这可以通过实现一个不同的类(可能从公共基础派生)来解决,一个称为 VoidContainer,另一个称为 ReturnsContainer (或类似的)。不过这对我来说似乎有点不太令人满意......

Given the following template:

template<class T>
class Container
{
private:

    boost::function<T> f;
};

... and its instantiation, perhaps as follows:


    Container<bool(int, int)> myContainer;

, is there a way to access the return type of the function description and compile conditionally against it? For example, if the caller specifies his function returns bool (as in the above case), I want to include a function that returns a value. If he specifies that the function is void, I don't want this function to be included. For example:


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

I'm guessing there is a solution here, but it probably involves some horrendously obfuscated template meta-programming solution. I know Gregor Cantor went mad contemplating infinity... template meta-programming kind-of has the same effect on me :p.

Thanks for any thoughts you might have.

RobinsonT

Edit: Obviously this can be solved by implementing a different class (perhaps derived from a common base), one called VoidContainer and the other called ReturnsContainer (or similar). However this seems a little unsatisfactory to me...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

诗化ㄋ丶相逢 2024-09-21 18:22:56

我认为您实际上不需要专门研究 void 返回类型。对于这种情况,允许 void 函数返回另一个 void 函数的“结果”。

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

int main()
{
    bar();
}

所以你唯一的问题是如何确定返回类型。

看来 boost::function 有一个 result_type 的 typedef (参见 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/non-void 结果,您可以使用 enable_ifdisable_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();
}

I don't think you actually need to specialize for void return type. A void function is allowed to return the "result" of another void function for exactly this scenario.

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

int main()
{
    bar();
}

So your only problem would be how to determine the return type.

It appears that boost::function has a typedef for result_type (see 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;

Edit:
Now that you know what the result_type is, and you do need to distinguish between void/non-void results, you can employ enable_if and disable_if. The only complication is that those only work with function templates, so a non-template foo calls a templated 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();
}
蓝戈者 2024-09-21 18:22:56

是的,您可以使用 < code>boost::function_traits,它有一个 result_type typedef。

Yes, you can use boost::function_traits, which has a result_type typedef.

烟花肆意 2024-09-21 18:22:56

取决于你想要什么,也许你让事情变得比必要的更复杂。如果在 void 情况下调用的 f 本身就是一个 void 函数,则可以只保留 return

显式返回“空值”是可以的:

void f() {
}

void g() {
   return f();
}

Depending on what you want to so, maybe you are making things more complicated than necessary. If the f you call in the void case is a void function itself, you can just keep the return.

Explicitly returning a "void value" is ok:

void f() {
}

void g() {
   return f();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文