簡體   English   中英

為什么非模板化函數具有相同的名稱和參數但返回類型不同是非法的? (但模板功能合法嗎?)

[英]Why is it illegal for non-templated functions to have same name and arguments but different return types? (but legal for template functions?)

我查看了一些相關的堆棧溢出線程,例如模板函數重載的這種情況使我無法理解

函數重載按返回類型?

但似乎都沒有給我我正在尋找的答案,至少不是一種容易讓我解釋的方式。

我的問題歸結為:從設計和技術的角度來看,為什么這樣做是合法的:

#include <iostream>

using namespace std;

template<class T>
void func(){
    cout << "Compiler inferred from void return value!\n";
}

template<class T>
int func(){
    cout << "Compiler inferred from int return value!\n";
    return 0;
}

int main(){
    void (*thisFunc)()=func<int>;
    int (*thatFunc)()=func<int>;
    thisFunc();
    thatFunc();
}

但不是這個:

#include <iostream>

using namespace std;

void func(){
    cout << "You won't see this because it won't compile!\n";
}

int func(){
    cout << "Nor this one!\n";
    return 0;
}

int main(){
    void (*thisFunc)()=func;
    int (*thatFunc)()=func;
    thisFunc();
    thatFunc();
}

值得一提的是,如果我在初始化thisFunc和thatFunc時沒有明確地給func一個任意模板參數,那么第一個例子將無法編譯。 兩者之間唯一的另一個區別是,第一個函數的函數是由完全無關的類型模板化的,除了它顯然允許我通過返回類型重載。 在這種情況下,編譯器甚至能夠對要調用的函數進行推斷,使得c ++中返回類型的函數重載的非法性對我來說有些困惑。 無論如何,我猜這是一個巧妙的技巧。

編輯:困擾我最多的是不一致性:在我真正考慮通過返回類型重載之前,我會想很長很難,但如果想要通過返回類型重載的人“修復”只是添加一個無意義的模板參數或顯然將函數包裝在命名空間內,然后我認為C ++應該或多或少地嚴格關於它認為不明確的東西。 是否有令人信服的理由為什么模板和命名空間需要此功能才能正常工作? 例如,如果不允許模板在我的示例中消除代碼歧義,那么是否存在一些不可行的代碼示例? 我從語言設計的角度提出要求,而不是編譯器合規性的觀點。

它通常不是無效的:有一種方法可以在返回類型上重載非模板函數。 它只會像你做的那樣無效。

namespace A {
  void func() {}
}
namespace B {
  int func() { return 0; }
}
using A::func;
using B::func;
int main(){
  void (*thisFunc)()=func;
  int (*thatFunc)()=func;
  thisFunc();
  thatFunc();
}

這編譯,鏈接和運行良好。

由於這是有效的並且被實際實現所接受,因此應該清楚的是,沒有技術原因導致您的代碼無效。 不可否認,它需要對名稱修改進行一些更改,因為通常非模板函數在修改后的名稱中沒有返回類型,但它很容易實現。

剩下的是一個合乎邏輯的原因:在返回類型上重載非模板函數幾乎肯定是一個錯誤。 它使得函數在正常情況下不可調用,它對常見錯誤(在一個地方更改聲明而忘記其他地方)的診斷非常差,它的使用極其有限,所以就是不要這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM