代码之家  ›  专栏  ›  技术社区  ›  pauldoo

提取函数的返回类型而不调用它(使用模板?)

  •  8
  • pauldoo  · 技术社区  · 15 年前

    我正在寻找一种在C++中提取函数返回类型的方法(不调用它)。我认为这需要一些模板魔法。

    float Foo();
    int Bar();
    
    magic_template<Foo>::type var1; // Here 'var1' should be of type 'float'
    magic_template<Bar>::type var2; // and 'var2' should be of type 'int'
    

    我目前正在调查 magic_template 可能已实施,但目前尚未找到解决方案。

    有什么想法吗?

    7 回复  |  直到 12 年前
        1
  •  7
  •   David Rodríguez - dribeas    15 年前

    看看boost type traits 图书馆,尤其是 function_traits

    注意,功能是基于类型的,而不是具体的函数,因此您可能需要在那里添加一些额外的代码。


    在做了一些小测试之后,这可能不是你真正需要的,如果是的话,“一些额外的代码”将非常重要。问题是 function_特征 模板作用于函数签名,而不是实际的函数指针,因此问题已从“从函数指针获取返回类型”变为“从函数指针获取签名”,这可能是其中最难的部分。

        2
  •  5
  •   James Hopkin    15 年前

    typeof . Boost的 TypeOf 是一种非常接近的便携式解决方案。

    但是,如果可以组织代码,使工作在一个函数模板内完成 Foo Bar 如果可以通过,有一个直截了当的答案:

    template <class R>
    void test(R (*)())
    {
      R var1;
    }
    
    int main()
    {
      test(&Foo);
    }
    
        3
  •  5
  •   JoeG    15 年前

    Foo和Bar是函数,而不是函数类型,因此需要做一些额外的工作。

    #include <boost/typeof/typeof.hpp>
    #include <boost/type_traits.hpp>
    
    float Foo();
    int Bar();
    
    int main()
    {
      boost::function_traits<BOOST_TYPEOF(Foo)>::result_type f = 5.0f;
      boost::function_traits<BOOST_TYPEOF(Bar)>::result_type i = 1;
      return i;
    }
    

    编辑:

    • 这将适用于最多10个算术数的函数,对于最合理的使用来说,这应该足够了。
    • BOOST_TYPEOF的这种使用在不提供本机TYPEOF的平台上工作,因此具有合理的可移植性。
        4
  •  2
  •   peterchen    15 年前

    在C++0x中,使用 decltype

    有关这些问题的讨论以及为早期C++标准构建解决方案的尝试,请参阅此处:

    Scott Myers "challenge" (PDF)和 Andrei Alexandrescu trying to solve it

        5
  •  1
  •   Sergey K.    12 年前

    Boost 涉及):

    template <typename ReturnType> class clFunc0
    {
        typedef ReturnType ( *FuncPtr )();
    public:
        typedef ReturnType Type;
    };
    
    template <typename ReturnType> inline clFunc0<ReturnType> ResultType( ReturnType ( *FuncPtr )() )
    {
        return clFunc0<ReturnType>();
    }
    
    #define FUNC_TYPE( func_name ) decltype( ResultType( &func_name ) )::Type
    
    int test()
    {
        return 1;
    }
    
    int main()
    {
        FUNC_TYPE( test ) Value = 1;
    
        return Value;
    }
    

    gcc Test.cpp -std=gnu++0x
    
        6
  •  0
  •   pauldoo    15 年前

    正如dribeas所建议的,以下是我最终得出的解决方案:

    float Foo();
    int Bar();
    
    template<typename T> Monkey(T) {
        boost::function_traits< boost::remove_pointer<T>::type >::result_type var1 = ...;
        // Now do something
    }
    
    Monkey(Foo);
    Monkey(Bar);
    

    这并不是我最初的问题想要的形式,但对我来说已经足够接近了。

        7
  •  -1
  •   Sergey K.    12 年前

    尝试以下操作:

    template<class T> struct magic_template
    {};
    
    template<class T> struct magic_template<T()>
    {
        typedef T type;
    };