【问题标题】:Return type of function determined by the function itself函数的返回类型由函数本身决定
【发布时间】:2021-04-08 15:27:30
【问题描述】:

我正在尝试创建一个模板化函数,它根据给定的函数参数返回一些内容,目标是让函数在运行时找出它需要返回的内容。以如下代码为例:

// foo.h
#pragma once
class foo
{
public:
    enum type {
        ALPHA,
        BETA
    };

    enum version {
        ONE,
        TWO
    };

    foo(type t, version v) : m_type(t), m_version(v) {};

    type get_type() { return m_type; }
    version get_version() { return m_version; }

    template<typename T>
    T get_either(bool type);

private:
    type m_type;
    version m_version;
};

// foo.cpp
#include "foo.h"

template<typename T>
T foo::get_either(bool type) {
    if (type) {
        return get_type();
    }
    else {
        return get_version();
    }
}

// main.cpp
int main()
{
    foo a(foo::type::ALPHA, foo::version::ONE);

    a.get_type();
    a.get_version();

    a.get_either(true);
    ^^^^^ compiler error
}

这显然会因编译器错误而失败,但这甚至可能吗?在我的一生中,我无法弄清楚如何做到这一点,而且我真的很挣扎,甚至在模板的世界中从哪里开始。

编辑:我可能应该更好地解释我的用例,请参见下图。我首先想看看我是否可以通过提示自己得到它,而不是让别人帮我弄清楚。

我将有一个vector 的接口类。我想遍历这个列表,并调用get_sensor() 来检索投射到派生类的传感器。我现在通过检查传感器的type,然后将dynamic_casting 到它需要的任何派生类来“手动”执行此操作,但我想知道这是否可以通过variant 自动完成。

【问题讨论】:

  • 你不能有多个具有相同签名的函数,只有返回类型不同。
  • 使用std::variant?
  • 您的用例是什么? (std::variant 有效,或者作为 Marek R 的答案,函数重载。)
  • @Devolus 请看我更新的问题,这不能用variantany 解决吗? @Someprogrammerdude 我看了variant 并进行了一些实验,但我不确定是否有可能实现我想要的,请参阅我更新的问题。 @Unapiedra 我更新了我的问题。

标签: c++ templates variant


【解决方案1】:

这是引入std::variantstd::any 来解决的问题之一。模板是编译时的东西,它们在代码编译后不存在,因此无法在运行时更改类型。 std::variant 允许您返回可以是一组类型之一的事物。 std::any 让你返回一个可以是任何东西的东西。

【讨论】:

    【解决方案2】:

    您可以使用函数重载并使用如下输出参数:

    #include <iostream>
    
    class foo
    {
    public:
        enum type {
            ALPHA,
            BETA
        };
    
        enum version {
            ONE,
            TWO
        };
    
        foo(type t, version v) : m_type(t), m_version(v) {};
    
        type get_type() { return m_type; }
        version get_version() { return m_version; }
    
        void get_either(type &t);
        void get_either(version &v);
    
    private:
        type m_type;
        version m_version;
    };
    
    
    void foo::get_either(type &t) {
        t =  get_type();
    }
    
    void foo::get_either(version &v) {
        v = get_version();
    }
    
    // main.cpp
    int main()
    {
        foo a(foo::type::ALPHA, foo::version::ONE);
    
        a.get_type();
        a.get_version();
    
        foo::type type;
        foo::version ver;
    
        a.get_either(type);
        a.get_either(ver);
    }
    

    https://godbolt.org/z/P3rKW8Tsj

    【讨论】:

      【解决方案3】:

      你可以做类似的事情,但只要参数是编译时间:

      template<bool type>
      auto foo::get_either() {
          if constexpr (type) {
              return get_type();
          }
          else {
              return get_version();
          }
      }
      

      当然,如果您的布尔值是严格运行时的,这将不起作用。在这种情况下,我建议使用像 std::variant 这样的 sum 类型。

      【讨论】:

        猜你喜欢
        • 2018-03-19
        • 2021-07-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-19
        • 2018-04-09
        • 1970-01-01
        相关资源
        最近更新 更多