C++ 根据返回值重载C++函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/226144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:52:39  来源:igfitidea点击:

Overload a C++ function according to the return value

c++functionpuzzleoverloading

提问by Motti

We all know that you can overload a function according to the parameters:

我们都知道可以根据参数重载一个函数:

int mul(int i, int j) { return i*j; }
std::string mul(char c, int n) { return std::string(n, c); } 

Can you overload a function according to the return value? Define a function that returns different things according to how the return value is used:

你能根据返回值重载一个函数吗?根据返回值的使用方式定义一个返回不同内容的函数:

int n = mul(6, 3); // n = 18
std::string s = mul(6, 3); // s = "666"
// Note that both invocations take the exact same parameters (same types)

You can assume the first parameter is between 0-9, no need to verify the input or have any error handling.

您可以假设第一个参数在 0-9 之间,无需验证输入或进行任何错误处理。

回答by paercebal

You have to tell the compiler which version to use. In C++, you can do it three ways.

您必须告诉编译器使用哪个版本。在 C++ 中,您可以通过三种方式做到这一点。

Explicitly differentiate the calls by typing

通过键入显式区分调用

You somewhat cheated because you sent an integer to a function waiting for a char, and wrongly sent the number six when the char value of '6' is not 6 but 54 (in ASCII):

你有点作弊,因为你发送了一个整数到一个等待字符的函数,并且当 '6' 的字符值不是 6 而是 54(在 ASCII 中)时错误地发送了数字 6:

std::string mul(char c, int n) { return std::string(n, c); }

std::string s = mul(6, 3); // s = "666"

The right solution would be, of course,

正确的解决方案当然是

std::string s = mul(static_cast<char>(54), 3); // s = "666"

This was worth mentioning, I guess, even if you did not want the solution.

这值得一提,我想,即使您不想要解决方案。

Explicitly differentiate the calls by dummy pointer

通过虚拟指针显式区分调用

You can add a dummy parameter to each functions, thus forcing the compiler to choose the right functions. The easiest way is to send a NULL dummy pointer of the type desired for the return:

您可以为每个函数添加一个虚拟参数,从而迫使编译器选择正确的函数。最简单的方法是发送返回所需类型的 NULL 虚拟指针:

int mul(int *, int i, int j) { return i*j; }
std::string mul(std::string *, char c, int n) { return std::string(n, c); }

Which can be used with the code:

可以与代码一起使用:

int n = mul((int *) NULL, 6, 3); // n = 18
std::string s = mul((std::string *) NULL, 54, 3); // s = "666"

Explicitly differentiate the calls by templating the return value

通过模板化返回值显式区分调用

With this solution, we create a "dummy" function with code that won't compile if instantiated:

使用此解决方案,我们创建了一个“虚拟”函数,其代码在实例化时将无法编译:

template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

You'll note this function won't compile, which is a good thing because we want only to use some limited functions through template specialization:

你会注意到这个函数不会编译,这是一件好事,因为我们只想通过模板特化来使用一些有限的函数:

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

template<>
std::string mul<std::string>(int i, int j)
{
   return std::string(j, static_cast<char>(i)) ;
}

Thus, the following code will compile:

因此,将编译以下代码:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>(54, 3); // s = "666"

But this one won't:

但这个不会:

short n2 = mul<short>(6, 3); // error: assignment of read-only variable ‘k'

Explicitly differentiate the calls by templating the return value, 2

通过模板化返回值来显式区分调用,2

Hey, you cheated, too!

哎,你也被骗了!

Right, I did use the same parameters for the two "overloaded" functions. But you did start the cheating (see above)...

是的,我确实对两个“重载”函数使用了相同的参数。但你确实开始作弊(见上文)......

^_^

^_^

More seriously, if you need to have different parameters, then you will to write more code, and then have to explicitly use the right types when calling the functions to avoid ambiguities:

更严重的是,如果您需要有不同的参数,那么您将编写更多代码,然后在调用函数时必须明确使用正确的类型以避免歧义:

// For "int, int" calls
template<typename T>
T mul(int i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
int mul<int>(int i, int j)
{
   return i * j ;
}

// For "char, int" calls
template<typename T>
T mul(char i, int j)
{
   // If you get a compile error, it's because you did not use
   // one of the authorized template specializations
   const int k = 25 ; k = 36 ;
}

template<>
std::string mul<std::string>(char i, int j)
{
   return std::string(j, (char) i) ;
}

And this code would be used as such:

这段代码将被这样使用:

int n = mul<int>(6, 3); // n = 18
std::string s = mul<std::string>('6', 3); // s = "666"

And the following line:

以及以下行:

short n2 = mul<short>(6, 3); // n = 18

Would still not compile.

还是不会编译。

Conclusion

结论

I love C++...

我喜欢 C++...

:-p

:-p

回答by Coincoin

class mul
{
public:
    mul(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

Not that I would use that.

并不是说我会使用它。

回答by Eclipse

If you wanted to make mulbe a real function instead of a class, you could just use an intermediate class:

如果你想mul成为一个真正的函数而不是一个类,你可以使用一个中间类:

class StringOrInt
{
public:
    StringOrInt(int p1, int p2)
    {
        param1 = p1;
        param2 = p2;
    }
    operator int ()
    {
        return param1 * param2;
    }

    operator std::string ()
    {
        return std::string(param2, param1 + '0');
    }

private:
    int param1;
    int param2;
};

StringOrInt mul(int p1, int p2)
{
    return StringOrInt(p1, p2);
}

This lets you do things like passing mulas a function into std algorithms:

这使您可以执行诸如将mul函数传递给 std 算法之类的操作:

int main(int argc, char* argv[])
{
    vector<int> x;
    x.push_back(3);
    x.push_back(4);
    x.push_back(5);
    x.push_back(6);

    vector<int> intDest(x.size());
    transform(x.begin(), x.end(), intDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 15 20 25 30
    for (vector<int>::const_iterator i = intDest.begin(); i != intDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    vector<string> stringDest(x.size());
    transform(x.begin(), x.end(), stringDest.begin(), bind1st(ptr_fun(&mul), 5));
    // print 555 5555 55555 555555
    for (vector<string>::const_iterator i = stringDest.begin(); i != stringDest.end(); ++i)
        cout << *i << " ";
    cout << endl;

    return 0;
}

回答by MrZebra

No.

不。

You can't overload by return value because the caller can do anything (or nothing) with it. Consider:

你不能通过返回值来重载,因为调用者可以用它做任何事情(或什么都不做)。考虑:

mul(1, 2);

mul(1, 2);

The return value is just thrown away, so there's no way it could choose an overload based on return value alone.

返回值只是被丢弃了,因此它无法仅根据返回值来选择重载。

回答by Pieter

Use implicit conversion in an in between class.

在类之间使用隐式转换。

class BadIdea
{
  public:
    operator string() { return "silly"; }
    operator int() { return 15; }
};

BadIdea mul(int, int)

You get the idea, terrible idea though.

你明白了,虽然这个想法很糟糕。

回答by Federico A. Ramponi

Let mul be a class, mul(x, y) its constructor, and overload some casting operators.

让 mul 是一个类, mul(x, y) 是它的构造函数,并重载一些转换运算符。

回答by Franci Penov

You cannot overload a function based on the return value only.

不能仅根据返回值重载函数。

However, while strictly speaking this is not an overloaded function, you could return from your function as a result an instance of a class that overloads the conversion operators.

然而,虽然严格来说这不是一个重载函数,但您可以从您的函数返回一个重载转换运算符的类的实例。

回答by Brian

I presume you could have it return some weird type Foo that just captures the parameters and then Foo has an implicit operator int and operator string, and it would "work", though it wouldn't really be overloading, rather an implicit conversion trick.

我想你可以让它返回一些奇怪的类型 Foo ,它只捕获参数,然后 Foo 有一个隐式 operator int 和 operator string,它会“工作”,尽管它不会真正重载,而是隐式转换技巧。

回答by John Littleberry Sr

Short and simple, the answer is NO. In C++ the requirements are:

简短而简单,答案是否定的。在 C++ 中,要求是:

1: name of functions MUST be the same
2: set of arguments MUST differ
*The return type can be the same or different

1:函数名称必须相同
2:参数集必须不同
*返回类型可以相同或不同

//This is not valid
    int foo();
    float foo();

    typedef int Int;

    int foo(int j);
    int foo(Int j);

//Valid:
   int foo(int j);
   char* foo(char * s);
   int foo(int j, int k);
   float foo(int j, float k);
   float foo(float j, float k);

回答by mempko

You can use the functor solution above. C++ does not support this for functions except for const. You can overload based on const.

您可以使用上面的函子解决方案。C++ 不支持除了 const 之外的函数。您可以基于 const 进行重载。