【问题标题】:How to deduce C++ return type in template?如何推断模板中的 C++ 返回类型?
【发布时间】:2016-04-15 10:02:07
【问题描述】:

我有一个函子,我希望自动推导出返回类型。我该怎么做?

template <typename _ScalarL, typename _ScalarR>
struct Multi
{
    DEDUCEDTYPE operator()(_ScalarL input1, _ScalarR input2) const
    {
        return input1 * input2;
    }
};

int main(){
    Multi<int, double> mt;
    mt(1,2.0);
}

如何自动获取DEDUCEDTYPE

【问题讨论】:

  • 如果您将DEDUCEDTYPE 重新拼写为auto,它应该已经可以工作了(前提是您使用的是C++14)。
  • 请注意,以下划线大写开头的名称是为实现保留的。
  • @KerrekSB 我不能将 C++11 或更高版本用于低 g++ 版本............
  • 在这种情况下,“为实现保留”意味着“只有编译器供应商可以这样做,而你不能”。
  • 在 c++11(以及decltype)之前,您必须使用所有可能的值创建自己的特征。

标签: c++ templates functor generic-programming c++03


【解决方案1】:

如何自动获得DEDUCEDTYPE [使用c++03]?

自动类型推导在 C++03 中是不可能的。如其他答案中所述,您可能必须手动创建自己的推理专业。

对于C++11/C++14

// For C++14, simply `auto` is enough
auto operator()(_ScalarL input1, _ScalarR input2) const
#if __cplusplus < 201402L
-> decltype(input1 * input2) // required for C++11
#endif

【讨论】:

    【解决方案2】:

    好吧,我相信在 c++11 之前,你注定要手动提供推论......你可以为此创建专门化的辅助结构:

    template <typename A, typename B>
    struct deduce { };
    
    template <>
    struct deduce<int, double> {
       typedef double type;
    };
    
    template <typename ScalarL, typename ScalarR>
    struct Multi
    {
        typename deduce<ScalarL, ScalarR>::type operator()(ScalarL input1, ScalarR input2) const
        {
            return input1 * input2;
        }
    };
    
    int main(){
        Multi<int, double> mt;
        mt(1,2.0);
    }
    

    编辑:

    更通用的方法是调用创建在推导结果类型时应考虑的类型的优先级层次结构。示例代码:

    #include <iostream>
    
    template <typename T>
    struct MoreGeneralNumber { };
    
    template <>
    struct MoreGeneralNumber<long>: MoreGeneralNumber<int> {};
    
    template <>
    struct MoreGeneralNumber<float>: MoreGeneralNumber<long> {};
    
    template <>
    struct MoreGeneralNumber<double>: MoreGeneralNumber<float> {};
    
    typedef char (&yes)[1];
    typedef char (&no)[2];
    
    template <bool L, bool R, typename LT, typename RT>
    struct MoreGeneral { };
    
    template <bool R, typename LT, typename RT>
    struct MoreGeneral<true, R, LT, RT> {
       typedef LT type;
    };
    
    template <typename LT, typename RT>
    struct MoreGeneral<false, true, LT, RT> {
       typedef RT type;
    };
    
    template <typename B, typename D>
    struct Host
    {
      operator B*() const;
      operator D*();
    };
    
    template <typename B, typename D>
    struct is_base_of
    {
      template <typename T> 
      static yes check(D*, T);
      static no check(B*, int);
    
      static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
    };
    
    template <typename L, typename R>
    struct Deduce: MoreGeneral<is_base_of<MoreGeneralNumber<R>, MoreGeneralNumber<L> >::value, 
                               is_base_of<MoreGeneralNumber<L>, MoreGeneralNumber<R> >::value, L, R >  {
    };
    
    template <typename ScalarL, typename ScalarR>
    struct Multi
    {
        typename Deduce<ScalarL, ScalarR>::type operator()(ScalarL input1, ScalarR input2) const
        {
            return input1 * input2;
        }
    };
    
    int main() {
       Multi<int, double> mt;
       std::cout << mt(1, 2.5) << std::endl; 
    }
    

    【讨论】:

    • 在 C++03 中,有 boost::result_of 我更愿意自己写东西。
    • @davidhigh 问题是 result_of 将要求操作符 * 用于原语将是一个以指针形式提供的函数......不幸的是我不知道在这里使用boost::result_of 的方法这将满足 OP 需求...
    • 啊,好的,我没听懂,谢谢指点。如果是这样,那么当然没有任何好处。 (对于简单的算术运算,可以使用boost::common_type
    猜你喜欢
    • 2015-12-14
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2021-12-09
    相关资源
    最近更新 更多