为什么主流的静态类型语言不支持按返回类型重载函数/方法?我想不出有什么能做到。这似乎并不比支持按参数类型重载更有用或更合理。为什么它不那么受欢迎呢?


当前回答

根据返回元素是标量还是数组,Octave允许不同的结果。

x = min ([1, 3, 0, 2, 0])
   ⇒  x = 0

[x, ix] = min ([1, 3, 0, 2, 0])
   ⇒  x = 0
      ix = 3 (item index)

Cf也是奇异值分解。

其他回答

好的答案!A.Rex的回答尤其详细且有启发性。正如他所指出的,c++在编译lhs = func()时确实会考虑用户提供的类型转换操作符;(func实际上是结构体的名称)。我的解决方法有点不同——不是更好,只是不同(尽管它基于相同的基本思想)。

而我想写的是……

template <typename T> inline T func() { abort(); return T(); }

template <> inline int func()
{ <<special code for int>> }

template <> inline double func()
{ <<special code for double>> }

.. etc, then ..

int x = func(); // ambiguous!
int x = func<int>(); // *also* ambiguous!?  you're just being difficult, g++!

我最终得到了一个使用参数化结构体(T =返回类型)的解决方案:

template <typename T>
struct func
{
    operator T()
    { abort(); return T(); } 
};

// explicit specializations for supported types
// (any code that includes this header can add more!)

template <> inline
func<int>::operator int()
{ <<special code for int>> }

template <> inline
func<double>::operator double()
{ <<special code for double>> }

.. etc, then ..

int x = func<int>(); // this is OK!
double d = func<double>(); // also OK :)

这种解决方案的一个好处是,任何包含这些模板定义的代码都可以为更多类型添加更多专门化。此外,您还可以根据需要对结构进行部分特殊化。例如,如果你想对指针类型进行特殊处理:

template <typename T>
struct func<T*>
{
    operator T*()
    { <<special handling for T*>> } 
};

作为一个负数,你不能写int x = func();用我的解决方案。你必须写int x = func<int>();。您必须显式地说明返回类型是什么,而不是让编译器通过查看类型转换操作符来确定它。我想说的是,“我的”解决方案和a . rex的解决方案都属于解决这个c++困境的帕累托最优方法:)

在. net中,有时我们使用一个参数来指示一个通用结果的期望输出,然后进行转换以得到我们期望的结果。

C#

public enum FooReturnType{
        IntType,
        StringType,
        WeaType
    }

    class Wea { 
        public override string ToString()
        {
            return "Wea class";
        }
    }

    public static object Foo(FooReturnType type){
        object result = null;
        if (type == FooReturnType.IntType) 
        {
            /*Int related actions*/
            result = 1;
        }
        else if (type == FooReturnType.StringType)
        {
            /*String related actions*/
            result = "Some important text";
        }
        else if (type == FooReturnType.WeaType)
        {
            /*Wea related actions*/
            result = new Wea();
        }
        return result;
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Expecting Int from Foo: " + Foo(FooReturnType.IntType));
        Console.WriteLine("Expecting String from Foo: " + Foo(FooReturnType.StringType));
        Console.WriteLine("Expecting Wea from Foo: " + Foo(FooReturnType.WeaType));
        Console.Read();
    }

也许这个例子也有帮助:

C++

    #include <iostream>

enum class FooReturnType{ //Only C++11
    IntType,
    StringType,
    WeaType
}_FooReturnType;

class Wea{
public:
    const char* ToString(){
        return "Wea class";
    }
};

void* Foo(FooReturnType type){
    void* result = 0;
    if (type == FooReturnType::IntType) //Only C++11
    {
        /*Int related actions*/
        result = (void*)1;
    }
    else if (type == FooReturnType::StringType) //Only C++11
    {
        /*String related actions*/
        result = (void*)"Some important text";
    }
    else if (type == FooReturnType::WeaType) //Only C++11
    {
        /*Wea related actions*/
        result = (void*)new Wea();
    }
    return result;
}

int main(int argc, char* argv[])
{
    int intReturn = (int)Foo(FooReturnType::IntType);
    const char* stringReturn = (const char*)Foo(FooReturnType::StringType);
    Wea *someWea = static_cast<Wea*>(Foo(FooReturnType::WeaType));
    std::cout << "Expecting Int from Foo: " << intReturn << std::endl;
    std::cout << "Expecting String from Foo: " << stringReturn << std::endl;
    std::cout << "Expecting Wea from Foo: " << someWea->ToString() << std::endl;
    delete someWea; // Don't leak oil!
    return 0;
}

根据返回元素是标量还是数组,Octave允许不同的结果。

x = min ([1, 3, 0, 2, 0])
   ⇒  x = 0

[x, ix] = min ([1, 3, 0, 2, 0])
   ⇒  x = 0
      ix = 3 (item index)

Cf也是奇异值分解。

如果函数被返回类型重载并且有这两个重载

int func();
string func();

在看到这样的调用时,编译器无法确定调用这两个函数中的哪一个

void main() 
{
    func();
}

由于这个原因,语言设计者通常不允许返回值重载。

然而,有些语言(如MSIL)允许按返回类型重载。当然,它们也面临上述困难,但它们有变通办法,为此您必须查阅它们的文档。

如前所述,对仅因返回类型不同而不同的函数的模糊调用会引入模糊。 模糊性会导致有缺陷的代码。 必须避免有缺陷的代码。

试图模糊化所带来的复杂性表明这不是一个好的hack。 除了智力练习之外,为什么不使用带有引用参数的过程呢?

procedure(reference string){};
procedure(reference int){};
string blah;
procedure(blah)