【问题标题】:Template member function unable to infer type automatically模板成员函数无法自动推断类型
【发布时间】:2021-03-04 12:10:21
【问题描述】:

我想做的是让函数根据输入返回不同的类型。 (本质上是返回类型的“重载”)

我对函数进行了模板化,但它不能自动推断类型,我必须手动输入所需的类型。

#include <iostream>

using namespace std;

struct S {

    template<typename T>
    T Get(int type) {
        if (type == 0) {
            return 4;
        } else if (type == 1) {
            return true;
        } else {
            return -1;
        }
    };

};

int main() {
    cout << boolalpha;

    S s;
    
    // ok
    int x = s.Get<int>(0); // return an integer
    bool y = s.Get<bool>(1); // return a boolean
    
    // ERROR
    // the end goal is something like this
    // is there a better way to handle this?
    int a = s.Get(0);
    bool b = s.Get(1);

    cout << "x: " << x << '\n'; // “x: 4”
    cout << "y: " << y << '\n'; // “y: true”

}

【问题讨论】:

  • 我使用的是 C++ 17。
  • C++ 中没有返回类型的重载。可以返回一个变体,它本质上是一个类型安全的联合,一次可以包含一个类型。
  • @Peter 我已经足够接近一个有利的结果,问题是调用时我不能只使用 Get();,我必须按顺序使用 Get()让它工作。我想知道是否可以让模板自动推断类型。
  • @xKaihatsu - 您认为在调用some_S.Get(some_integral_value) 中的信息是编译器推断Get() 成员函数的返回类型,特别是如果(在调用点)@987654324 @成员函数已声明但未定义。

标签: c++ function class templates overloading


【解决方案1】:

如果你有 C++17,那么你可以像这样使用if-constexpr

struct S {

    template<int type>
    auto Get() {
        if constexpr (type == 0) {
            return 4;
        }
        else if constexpr (type == 1) {
            return true;
        }
        else {
            return -1;
        }
    };

};

现在根据type 的值,正确的if-constexpr 分支将被编译并返回适当的类型。

你可以像这样使用上面的代码:

S s;

int x = s.Get<0>(); // return an integer
bool y = s.Get<1>(); // return a boolean

这是demo

请注意,type 值必须在编译时已知。在 C++ 中,你不能有一个函数在运行时返回不同类型的值。您必须使用 std::variantstd::any 来执行此操作。

【讨论】:

  • 这是一个超级简洁的 c++17 答案。 constexpr if 做得很好,有时我会忘记它的存在。这是最好的答案。
【解决方案2】:

对于您的最终目标,您可能需要一些模板专业化。像这样的东西可以工作:

template<unsigned S>
struct getHelp; // A helper to help us switch on the number, to get the type.

template<>
struct getHelp<0> { // If our number is 0, we have int type with value 4.
    constexpr static int value = 4;
};

template<>
struct getHelp<1> { // If our number is 1, we have bool type value true.
    constexpr static bool value = true;
};

template<unsigned S>  // We have our function, it overloads the return type based
                      // on that that of the return type of our helper.
constexpr auto get() -> decltype(getHelp<S>::value) {
    return getHelp<S>::value;
}

用法如下:

auto a = get<1>();

注意:如果您的意图是让指示您的类型的数字是动态的(即由用户传入),那么您尝试做的事情是不可能的。 c++ 是一种静态类型的语言,你能做的最好的事情就是使用 std::variant 和所有可能的类型。

Here is a live example

【讨论】:

    【解决方案3】:

    这是不可能的,因为在编译时必须知道类型,而 C++ 不支持 constexpr 函数参数。那就是:

    // valid
    template <int key> 
    auto fun() { if constexpr (key==0) return true; }
    
    // unsupported
    auto fun(constexpr int key)
    { if constexpr (key == 0) return true; }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多