C++で戻り値の型推論

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
774

C++で戻り値の型推論

#1

投稿記事 by 774 » 6年前

関数の戻り値の型を推論させるにはどうすればよいのでしょうか。

下のコードで、19、20行目をそれぞれget<int>, get<char>と書き直せばコンパイルが通ることは確認しました。
しかし、例えばmax関数はmax<int>と書かなくてもmax(1,2)のように呼びだせば自動でint型と判断され、のint型の2が返ってきますが、このような推論を関数の引数ではなく戻り値で行うにはどうすればよいのでしょうか。

コード:

#include <cstdio>

void get(int &i){
    scanf("%d",&i);
}

void get(char &c){
    scanf("%c",&c);
}

template<typename T>
T get(){
    T t;
    get(t);
    return t;
}

int main(){
    int i=get();  // ここではT get(),void get(char &c)が呼ばれ、
    char c=get(); // ここではT get(),void get(int &)が呼ばれてほしい
}
コンパイルエラー

コード:

test.cpp: In function ‘int main()’:
test.cpp:19:15: error: no matching function for call to ‘get()’
     int i=get();
               ^
test.cpp:19:15: note: candidate is:
test.cpp:12:3: note: template<class T> T get()
 T get(){
   ^
test.cpp:12:3: note:   template argument deduction/substitution failed:
test.cpp:19:15: note:   couldn't deduce template parameter ‘T’
     int i=get();
               ^
test.cpp:20:16: error: no matching function for call to ‘get()’
     char c=get();
                ^
test.cpp:20:16: note: candidate is:
test.cpp:12:3: note: template<class T> T get()
 T get(){
   ^
test.cpp:12:3: note:   template argument deduction/substitution failed:
test.cpp:20:16: note:   couldn't deduce template parameter ‘T’
     char c=get();
g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2です

box
記事: 1746
登録日時: 9年前

Re: C++で戻り値の型推論

#2

投稿記事 by box » 6年前

get()の実装と呼び出しとで
引数と戻り値がごっちゃになっているように見えるのは、
きっと気のせいですよね…。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

774

Re: C++で戻り値の型推論

#3

投稿記事 by 774 » 6年前

失礼しました。実装にはアンダーバーがつきます。

コード:

#include <cstdio>
 
void get_(int &i){
    scanf("%d",&i);
}
 
void get_(char &c){
    scanf("%c",&c);
}
 
template<typename T>
T get(){
    T t;
    get_(t);
    return t;
}
 
int main(){
    int i=get();  // ここではT get(),void get(char &c)が呼ばれ、
    char c=get(); // ここではT get(),void get(int &)が呼ばれてほしい
}

アバター
h2so5
副管理人
記事: 2212
登録日時: 9年前
住所: 東京
連絡を取る:

Re: C++で戻り値の型推論

#4

投稿記事 by h2so5 » 6年前

引数からの推論は不可能です。かならずテンプレート引数を指定する必要があります。

774

Re: C++で戻り値の型推論

#5

投稿記事 by 774 » 6年前

レスありがとうございます。引数にとることにします。

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: C++で戻り値の型推論

#6

投稿記事 by tk-xleader » 6年前

 解決済みのトピックに横槍入れて申し訳ありません。
 あんまりうまい手ではありませんけど、ユーザー定義の変換演算子を使えば、それっぽいコードは書けます。

コード:

#include <cstdio>
 
void get_(int &i){
    std::scanf("%d",&i);
}
 
void get_(char &c){
    std::scanf("%c",&c);
}

class returner{
public:
	template<typename T>operator T()const{
		T t;
		get_(t);
		return t;
	}
};
 
returner get(){
    return returner();
}
 
int main(){
    int i=get();  // ここではT get(),void get(char &c)が呼ばれ、
    char c=get(); // ここではT get(),void get(int &)が呼ばれてほしい
    std::printf("%d,%c",i,c);
}

774

Re: C++で戻り値の型推論

#7

投稿記事 by 774 » 6年前

テンプレート関数呼び出した場合、実装されているテンプレート関数をコピーして、
呼び出された型全てに対してTを置換した関数がコンパイラによって生成される(テンプレートクラスでも同様)という理解でよいでしょうか。

「No.3のコードが通らない理由は

コード:

template<typename T> T get(){
    T t;
    get(t);
    return t;
}
でのTがint,charに置換されたもの

コード:

int get(){
    int t;
    get(t);
    return t;
}

char get(){
    char t;
    get(t);
    return t;
}
が生成されるが、戻り値でのポリモーフィズムは効かないためエラーになる。
で、No: 6が通る理由は、

コード:

class returner{
public:
    template<typename T>operator T()const{
        T t;
        get_(t);
        return t;
    }
};

コード:

class returner{
public:
    operator int()const{
        int t;
        get_(t);
        return t;
    }
    operator char()const{
        char t;
        get_(t);
        return t;
    }
};
にコピー・置換され、returnerからint/charへの変換をそれぞれ定義したことになるため通る。」
ということで良いですか?

アバター
tk-xleader
記事: 153
登録日時: 9年前
連絡を取る:

Re: C++で戻り値の型推論

#8

投稿記事 by tk-xleader » 6年前

>774さん

概ねそんな理解でいいと思います。

閉鎖

“C言語何でも質問掲示板” へ戻る