機能過負荷による戻り値の型?
-
22-07-2019 - |
質問
なぜなり主流の静的型付き言語でサポート機能-方法の過負荷による戻り値の型?思いつかないのがいます。そうでない有理上支援の過負荷によるパラメータのタイプです。かないのか?
解決
に反するなどと言って過負荷による戻り値の型 は 可能 は による現代の言語である。通常の申立てがこのようなコード
int func();
string func();
int main() { func(); }
できない func()
が呼び出されます。この解決されながら、その方法:
- て予測可能な方法を決定する関数が呼び出される。
- いような事態が発生した場合、このコンパイル時にエラーとなります。しかし、このコマンドが適用される機能のプログラマdisambiguateなど
int main() { (string)func(); }
. - な副作用があります。な副作用ときは絶対に使わないでください関数の戻り値のコンパイラを回避できるもの呼び出し機能します。
二つの言語そして(ab使用過負荷による戻り値の型: Perl や ウ.についてご説明いうことになったと言われています。
に Perl, があることは区別 スカラー や リスト コンテキスト(およびその他がいふりがありになっています。毎内蔵機能のPerlらないんですけどによって 文脈 で呼び出されます。例えば、 join
オペレーターの力リストのコンテキストをもっているが、 scalar
オペレーターの力のスカラーの文脈での比較:
print join " ", localtime(); # printed "58 11 2 14 0 109 3 13 0" for me right now
print scalar localtime(); # printed "Wed Jan 14 02:12:44 2009" for me right now.
オペレータ毎のPerlのになるスカラーコンテキストもリストの文脈れる場合がありますので別のとする。(こじゃないランダム作用素のような localtime
.ご利用の場合配列 @a
リスト的には、この配列を返しま、スカラー的には、この数を返します。したがって、たとえば、 print @a
プリントアウトしたりすることの要素が print 0+@a
版画のサイズとなります。 また、オペレータ毎で 力 コンテキストなど加 +
軍スカラートします。各エントリ man perlfunc
書類です。例えば、こちらのエントリ glob EXPR
:
リストの文脈を返しまれ 空のリストのファイル名の拡張に の値
EXPR
などの標準 Unixシェル/bin/csh
思います。に スカラー、globを繰り返して調べてを通じて などのファイル名の拡張、 undefリストが消耗している。
などから持ち直している"というのは関係のリストスカラー。も man perlfunc
という
覚えて以下の重要なルールに関連付けます:"と思える文が多いことに 行動の発現量リスト コンテキストが動作しスカラー コンテキスト。いられることもありますが は全然違う。各 オペレーターの機能を決める のような価値が重要であ 適切返却しますスカラー コンテキスト一部の事業者を返します 長さのリストのいかなる 返されているリストのコンテキスト一部の 事業者の最初の値 の一覧です。一部の事業者を返します 最終価値の一覧です。一部の 事業者を返しカウントの成功 ます。一般的に、いか したい場合を除き、いの一貫性を追求します。
しているのではなく、単純物の有する単機能しい単純変換します。実際、私が選んだのは localtime
例することにしました。
だけでなく、組込みコマンドとしてこの行動です。ユーザー定義できる機能を利用 wantarray
, することができますの区別リストスカラー、ボトします。そのため、たとえば、決めることができないいわゆるvoidコンテキスト
まもな true 過負荷による返り値がまだ一機能であると言われ、コンテキストでの呼び出して、その行為を行ってまいります。しかし、このことは相当(および類似どのようにPerlすることを認めていません通常通りオーバーロード、文字通り、その機能でかつその引数).また、でも解決した曖昧な状況をお話ししたように、これまでの初めにこれに応じます。Perlなエレベータが古風な柵式のなかの方法電話;それだけで話します。すべてのせいで何の文脈で機能を呼び出して、常にこのことにより
sub func {
if( not defined wantarray ) {
print "void\n";
} elsif( wantarray ) {
print "list\n";
} else {
print "scalar\n";
}
}
func(); # prints "void"
() = func(); # prints "list"
0+func(); # prints "scalar"
(注:私が言うのPerlのオペレーターがいます。これは重要です。)
ウ のその他のアプローチ、すなわちになっています。でもタイプシステムで書くことができは次のようなコード:
main = do n <- readLn
print (sqrt n) -- note that this is aligned below the n, if you care to run this
このコードを読み込み浮動小数点数を標準入力から、版画、その平方根です。しかし、それを見てびっくり。どのタイプ readLn
は readLn :: Read a => IO a
.つけることはしないということはできる Read
(正式には、型のインスタンスである Read
タイプクラス) readLn
きます。どのようなウると思い浮動小数点かかりますか?どのタイプ sqrt
は sqrt :: Floating a => a -> a
, は、基本的にこの sqrt
でのみ受け付けの浮動小数点数を入力として、ウ明うございました。
何が起きるウなのかを推測したいと思い?もあり少しも可能です。場合に利用しない戻り値で、単純な話の機能ます。しかし、ま い の戻り値を使用し、ウまで文句を言うことができな推定のタイプ:
main = do n <- readLn
print n
-- this program results in a compile-time error "Unresolved top-level overloading"
私はすぐに解決できるの曖昧さを指定するタイプしたい:
main = do n <- readLn
print (n::Int)
-- this compiles (and does what I want)
とにかく、この議論は過負荷による返り値はできるが、回答の質問です。
その他のご質問はなぜ言語でわからないないのである。ようその他の答えます。しかし、別の複数のコメント:の原則の理由であろうことをこの機会に混乱が真によりこの過負荷による引数の型です。で説明する必要がありますので根拠がしっかりとした個々の言語:
Ada:"が表示される最も単純な過負荷分解能のルールはすべてすべての情報としてコンテキストとしての可能-解決の過負荷を参考にした。このルールは単純ではないものです。での人間のリーダー読み取りを任意に大きステムのインストールログを削除し、恣意的に複雑な推論などの(g)。いることによってより良いルールである明示的なタスクの人リーダー又はコンパイラに出演しなければならない、このタスクとして自然人のリーダーとして可能です。"
C++(第7.4.1のBjarne Stroustrup、C++のプログラミング言語"):"戻り値の型がされていない過負荷。その理由は解決のための個別のオペレーターまたは関数呼び出しコンテキスト独立しています。発生していると考えること
float sqrt(float);
double sqrt(double);
void f(double da, float fla)
{
float fl = sqrt(da); // call sqrt(double)
double d = sqrt(da); // call sqrt(double)
fl = sqrt(fla); // call sqrt(float)
d = sqrt(fla); // call sqrt(float)
}
場合、戻り値の型を考慮してこなかったわけではありばができなくなりによってはコール sqrt()
分離を決定する機能が行われようとしていました。" (注、比較のため、ウありません 暗黙的な 換。)
コロジカルフットプリント"Java言語仕様9.4.1):"の継承メソッドの必要な戻り値の型の代用その他の継承方法そうでない場合、コンパイル時にエラーが発生します。" (有、まることを前提としない理由.私の理由で与えられますGoslingで"Javaプログラミングしたものがあります。かいにはコピー?私はベットでの"原理の少なくとも驚き"です。) しかし、楽しいとJavaに関して:のJVM を可能に 過負荷による返り値!これは、例えば、 Scala, アクセスできるので、 直接Java どんinternals.
PS.ついては、注意、実際にできる過負荷による返り値にはC++とですよね。目撃者:
struct func {
operator string() { return "1";}
operator int() { return 2; }
};
int main( ) {
int x = func(); // calls int version
string y = func(); // calls string version
double d = func(); // calls int version
cout << func() << endl; // calls int version
func(); // calls neither
}
他のヒント
場合が過負荷による戻り値の型を楽しむことができます。れ過負荷
int func();
string func();
そのコンパイラとギターの機能を呼び出する姿を見て話すこ
void main()
{
func();
}
このため、言語のデザイナーが不可戻り値の過負荷.
一部の言語などのMSIL)は い きの過負荷による戻ります。でも顔は上記の難コース、回避策、およ用いのに相談してください。
言語における、あなたは何点ぐらいになると思いを解決する以下の
f(g(x))
の場合 f
た過負荷 void f(int)
や void f(string)
や g
た過負荷 int g(int)
や string g(int)
?する必要があり何らかのdisambiguator.
ると思う場合に必要がある場合がありますこのことはより良い選択は、新しい名前を入力します。機能です。
盗んではC++の特定 回答からも非常に類似の問題 (惑わ?):
関数の戻り値型ないしそれを実現するためには、過負荷分解能でStroustrup(いり入れながら他のC++の建築家)た過負荷へのさまざまな取り組みが認脈で独立した'.見7.4.1-"過負荷および戻り値の型"から"C++プログラミング言語のうち、第三編"です。
その理由は解決のための個別のオペレーターまたは関数呼び出しコンテキスト独立しています。
それから、若いプナのみに基づいてどのように過負荷と呼ばれた-どのような結果を使用した場合で用いられるのです。実際、多くの機能がないときは、その結果を用の結果として利用していを表現。ひとつの要因にもなると思いこと"にあたり、このた場合には、戻り値の型の決議が多く通話が過多の機能が必要となる解決すべき複雑なルールはないのコンパイラを投げるエラーのこの呼び出しになりました。
と、藩を知って、C++過負荷分解能は、複雑な足として...
にウで可能なものではない機能過負荷.ウ用タイプ。プログラムを目にした:
class Example a where
example :: Integer -> a
instance Example Integer where -- example is now implemented for Integer
example :: Integer -> Integer
example i = i * 10
機能過負荷ではありませんので人気です。多言語などの見所もC++でもjavaやC#.すべての動的言語で表記:
define example:i
↑i type route:
Integer = [↑i & 0xff]
String = [↑i upper]
def example(i):
if isinstance(i, int):
return i & 0xff
elif isinstance(i, str):
return i.upper()
そのためあい点です。ほとんどの人が一番の趣味ではないかどうかの言語でのドロップシングルライン当たりはすっきりとした使用します。
パターンマッチングと似た機能過負荷、私も仕事も同様に。で共通のものでは有限の適用などと組み合わせた、よりプログラムはトリッキーをほとんどの言語に対応しています。
だが限りなく多くのより容易に導入できる機能の実装の言語を含む:
- 動的なタイピング
- 内部支援のための、リストや辞書およびunicode文字列
- 最適化(JIT型慮しコンパイル)
- 統合の展開ツール
- 図書館を支援
- コミュニティサポートや集会所
- 豊富な標準ライブラリ
- 良い書式
- Readエバール印刷プ
- 支援のための反射ング
良い回答!A.レックスの応答特に非常に詳しく勉強になりました。した点で、C++ は 考えるユーザによって提供された型変換事業者が作成 lhs = func();
(funcは本当の名前は、struct).私の回避策は異なり、異なる(このの基本的な考え方).
はっ た 書...
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>();
.おいて明示的に何と言っても、戻り値の型であるようにコンパイラをsussで見るタイプの変換。ういった"私の"ソリューション、A.レックスの両方に所属し、 パレート最適となフロント の方法で取り組むとC++のジレンマ:)
したい場合は負荷方法の異なる種類を返し、追加 ダミーパラメータのデフォルト値 の過負荷の執行を忘れないパラメータの種類が違うと思うので、過負荷のロジックの作品にはe.g delphi:
type
myclass = class
public
function Funct1(dummy: string = EmptyStr): String; overload;
function Funct1(dummy: Integer = -1): Integer; overload;
end;
利用でこのような
procedure tester;
var yourobject : myclass;
iValue: integer;
sValue: string;
begin
yourobject:= myclass.create;
iValue:= yourobject.Funct1(); //this will call the func with integer result
sValue:= yourobject.Funct1(); //this will call the func with string result
end;
しているのか-曖昧電話の機能だけが異なるタイプのご紹介と定義しています。曖昧さが不良品のコードです。欠陥コードなどを実施する必要がある。
複雑さによる曖昧性を示すことにあてはまるわけではないhack.ほかにも、知的な利用方法を参照パラメータ。
procedure(reference string){};
procedure(reference int){};
string blah;
procedure(blah)
この過負荷特徴ではない、これを見れば、若干の方法は異なります。考え、以下では、
public Integer | String f(int choice){
if(choice==1){
return new string();
}else{
return new Integer();
}}
の場合の言語かを返しオーバーロードでつくって、そこに対してパラメータの過負荷が重複しない.この問題の解決:
main (){
f(x)
}
に限りがございますので一f(int選択から選べます。
ます。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;
}
の記録 オクターブ で異なる結果による要素を返しているスカラー vs配列になります。
x = min ([1, 3, 0, 2, 0])
⇒ x = 0
[x, ix] = min ([1, 3, 0, 2, 0])
⇒ x = 0
ix = 3 (item index)
Cfも 特異値分解.
これは若干異なC++;わからない場合であると考えられる過負荷による戻り値の型です。でのテンプレートを専門とする行為の方法です。
util.h
#ifndef UTIL_H
#define UTIL_H
#include <string>
#include <sstream>
#include <algorithm>
class util {
public:
static int convertToInt( const std::string& str );
static unsigned convertToUnsigned( const std::string& str );
static float convertToFloat( const std::string& str );
static double convertToDouble( const std::string& str );
private:
util();
util( const util& c );
util& operator=( const util& c );
template<typename T>
static bool stringToValue( const std::string& str, T* pVal, unsigned numValues );
template<typename T>
static T getValue( const std::string& str, std::size_t& remainder );
};
#include "util.inl"
#endif UTIL_H
util.inl
template<typename T>
static bool util::stringToValue( const std::string& str, T* pValue, unsigned numValues ) {
int numCommas = std::count(str.begin(), str.end(), ',');
if (numCommas != numValues - 1) {
return false;
}
std::size_t remainder;
pValue[0] = getValue<T>(str, remainder);
if (numValues == 1) {
if (str.size() != remainder) {
return false;
}
}
else {
std::size_t offset = remainder;
if (str.at(offset) != ',') {
return false;
}
unsigned lastIdx = numValues - 1;
for (unsigned u = 1; u < numValues; ++u) {
pValue[u] = getValue<T>(str.substr(++offset), remainder);
offset += remainder;
if ((u < lastIdx && str.at(offset) != ',') ||
(u == lastIdx && offset != str.size()))
{
return false;
}
}
}
return true;
}
util.cpp
#include "util.h"
template<>
int util::getValue( const std::string& str, std::size_t& remainder ) {
return std::stoi( str, &remainder );
}
template<>
unsigned util::getValue( const std::string& str, std::size_t& remainder ) {
return std::stoul( str, &remainder );
}
template<>
float util::getValue( const std::string& str, std::size_t& remainder ) {
return std::stof( str, &remainder );
}
template<>
double util::getValue( const std::string& str, std::size_t& remainder ) {
return std::stod( str, &remainder );
}
int util::convertToInt( const std::string& str ) {
int i = 0;
if ( !stringToValue( str, &i, 1 ) ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int";
throw strStream.str();
}
return i;
}
unsigned util::convertToUnsigned( const std::string& str ) {
unsigned u = 0;
if ( !stringToValue( str, &u, 1 ) ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned";
throw strStream.str();
}
return u;
}
float util::convertToFloat(const std::string& str) {
float f = 0;
if (!stringToValue(str, &f, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float";
throw strStream.str();
}
return f;
}
double util::convertToDouble(const std::string& str) {
float d = 0;
if (!stringToValue(str, &d, 1)) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to double";
throw strStream.str();
}
return d;
}
この例は、使用機能過負荷の決議による戻り値の型がこのc++外のオブジェクトのクラスではテンプレートには専門機能シミュレーターによる戻り値の型の専用静的な方法です。
それぞれの convertToType
機能の呼び出し機能テンプレート stringToValue()
見れば、実施の内容又はアルゴリズムの機能テンプレートで呼び出し getValue<T>( param, param )
で復帰タイプ T
保で T*
渡されるの stringToValue()
機能テンプレートの一つとして、パラメータ。
以上のようなこと;C++なっている機構として機能過負荷による議決を返します。ありその他の構築や仕組みをしているところを知らずのうシミュレーの決議を返します。
こういうギャップ現代のC++用定義...なぜですか?
int func();
double func();
// example 1. → defined
int i = func();
// example 2. → defined
double d = func();
// example 3. → NOT defined. error
void main()
{
func();
}
できないのはなぜでC++コンパイラでをスローしませんエラーの例では"3"と 受け入れにコード例では"1+2"??
もの静的言語によって支援のジェネリック医薬品は、解決の問題です。前述のとおり、パラメータの負荷ありませんから、大変な作業だったと思いる金がかかる場合があります。だいたいどこの使用のジェネリック医薬品と呼んでいます。