【问题标题】:Is there a way to make a function return a typename?有没有办法让函数返回类型名?
【发布时间】:2016-04-10 05:59:49
【问题描述】:

我最近在做一个项目,并希望在执行非标准操作时优先考虑某些类型。为此,我试图以某种方式使用模板来确定正在使用哪种数据类型。我写的代码显然不起作用,但它让我知道我想要做什么

#include <iostream>

template <type1,type2>
typename determine(type1 a, type2 b)
{
    if (typeid(type1) == typeid(int) || typeid(type2) == typeid(int))
        return int;
    else return double;
}

int main()
{
    int a = 3;
    double b = 2;
    std::cout << (static_cast<determine(a, b)>(a) / static_cast<determine(a, b)>(b)) << std::endl;
}

有没有办法确定返回一些我可以实际用来决定使用什么数据类型的东西?

【问题讨论】:

    标签: c++ templates types


    【解决方案1】:

    您可以使用template metaprogramming 技术来实现您的目标。

    template <typename T1, typename T2> struct TypeSelector
    {
       using type = double;
    };
    
    template <typename T1> struct TypeSelector<T1, int>
    {
       using type = int;
    };
    
    template <typename T2> struct TypeSelector<int, T2>
    {
       using type = int;
    };
    
    template <> struct TypeSelector<int, int>
    {
       using type = int;
    };
    

    然后,使用:

    int main()
    {
        int a = 3, b = 2;
        using type1 = TypeSelector<decltype(a), decltype(b)>::type;
        std::cout << (static_cast<type1>(a) / static_cast<type1>(b)) << std::endl;
    
       float c = 4.5f;
       using type2 = TypeSelector<decltype(a), decltype(c)>::type;
       std::cout << (static_cast<type2>(a) / static_cast<type2>(c)) << std::endl;
    
       using type3 = TypeSelector<decltype(c), decltype(a)>::type;
       std::cout << (static_cast<type3>(c) / static_cast<type3>(a)) << std::endl;
    
    }
    

    【讨论】:

    • 你有一个“与”运算——问题是一个“或”。
    • @DieterLücking,我意识到了,正在编辑中:)
    • 我很确定,如果我的问题是一样的。我想通过我的 Delphi RAD Studio 调用 C++ 例程。现在我想给我们我的type Tinputvec,它是一个array of integer(动态),由delphi函数返回。现在我必须在我的 C++ 部分中使用这个命名类型。 std::vector &lt;int&gt; 与我命名的 Tinputvec 类型不匹配,并且出现编译错误。如何在我的 C++ 部分中使用我的命名类型 Tinputvec?谢谢
    • @WalterSchrabmair,我没有答案。
    【解决方案2】:

    我很确定您可以使用 std::conditional 和几个 std::is_same 限定符通过 || 逻辑组合来做到这一点:

    #include <iostream>
    #include <type_traits>
    
    
    template<class T1, class T2>
    using determine = typename std::conditional<
        std::is_same<T1,int>::value || std::is_same<T2,int>::value, 
        int, double>::type;
    
    int main()
    {
        int a = 3;
        double b = 2;
        long c = 3L;
    
        using type1 = determine<decltype(a),decltype(b)>;
        std::cout << (static_cast<type1>(a) / static_cast<type1>(b)) << std::endl;
    
        using type2 = determine<decltype(b),decltype(c)>;
        std::cout << (static_cast<type2>(b) / static_cast<type2>(c)) << std::endl;
    }
    

    【讨论】:

    • @rtpax 如果您想以函数形式使用它,您可以使用尾随返回类型以及此答案中的别名。
    【解决方案3】:

    这是您可以使用的另一种可行的解决方案。
    基本思想是依靠函数重载和sfinae来分派请求,避免多重定义。
    它遵循一个最小的工作示例:

    #include<type_traits>
    #include<utility>
    #include<cassert>
    
    template <typename T1, typename T2>
    typename std::enable_if<std::is_same<T1, int>::value or std::is_same<T2, int>::value, int>::type
    determineImpl(int, T1 a, T2 b) {
        return 42;
    }
    
    template <typename T1, typename T2>
    typename std::enable_if<not std::is_same<T1, int>::value and not std::is_same<T2, int>::value, double>::type
    determineImpl(char, T1 a, T2 b) {
        return .42;
    }
    
    template<typename... Args>
    auto determine(Args&&... args) -> decltype(determineImpl(0, std::forward<Args>(args)...)) {
        return determineImpl(0, std::forward<Args>(args)...);
    }
    
    int main() {
        auto v1 = determine(42, 'c');
        assert(v1 == 42);
        auto v2 = determine('c', .42);
        assert(v2 == .42);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-12-24
      • 2010-11-22
      • 1970-01-01
      • 2020-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多