テンプレート関数の再帰呼び出し

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

テンプレート関数の再帰呼び出し

#1

投稿記事 by h2so5 » 14年前

可変長テンプレート引数を使い、バイナリデータから任意の変数を復元してタプルで返す関数を作っています。

再帰呼び出しの最後でテンプレート引数なしの関数が呼ばれるため、5行目でダミーの関数を定義しているのですが、
コンパイルすると「適合する関数がありません」というエラーが出てしまいます。

どこが問題なのでしょうか?

追記:
Ubuntu + gcc 4.6.3
及び Ideone.com (http://ideone.com/6gzy5) で確認しました

コード:

#include <iostream>
#include <tuple>

// テンプレート引数が無いときのダミー関数
std::tuple<> GetDeserializedValue(const std::string& data) {return std::tuple<>();}

// 変数を一つずつ復元する関数
template<class First, class... Rest>
std::tuple<First, Rest...> GetDeserializedValue(const std::string& data)
{
    std::string buffer(data);
    const First& value = *reinterpret_cast<const First*>(buffer.data());
    buffer.erase(sizeof(First));
    
    // 後続するテンプレート引数を使って再帰呼び出しをして、結果のタプルを連結する
    return std::tuple_cat(std::tuple<First>(value), GetDeserializedValue<Rest...>(buffer));
}

// バッファから変数を復元し、タプルで返す関数
template<class... Types>
std::tuple<Types...> Deserialize(const std::string& data)
{
    return GetDeserializedValue<Types...>(data);
}

int main() {
	Deserialize<int, double>("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
	return 0;
}
Error:

コード:

prog.cpp: In function 'std::tuple<_Head, _Tail ...> GetDeserializedValue(const std::string&) [with First = double, Rest = {}, std::string = std::basic_string<char>]':
prog.cpp:16:90:   instantiated from 'std::tuple<_Head, _Tail ...> GetDeserializedValue(const std::string&) [with First = int, Rest = {double}, std::string = std::basic_string<char>]'
prog.cpp:23:47:   instantiated from 'std::tuple<_Elements ...> Deserialize(const std::string&) [with Types = {int, double}, std::string = std::basic_string<char>]'
prog.cpp:27:66:   instantiated from here
prog.cpp:16:90: error: no matching function for call to 'GetDeserializedValue(std::string&)'

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: テンプレート関数の再帰呼び出し

#2

投稿記事 by beatle » 14年前

原因は推測できますが解決策がまだ思い浮かびません。
原因は恐らく、GetDeserializedValue<>(const std::string&)という関数を呼ぼうとして見つからないということです。
ダミー関数は普通の関数であってテンプレート関数ではないので、GetDeserializedValue<>()などと<>が付いているとマッチしないのだと思います。

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

Re: テンプレート関数の再帰呼び出し

#3

投稿記事 by h2so5 » 14年前

以下のように定義したところコンパイルが通りましたので、解決とさせていただきます。

参考URL
http://daily.belltail.jp/?p=195

コード:

// テンプレート引数が1つになった時のダミー関数
template<class First>
std::tuple<First> GetDeserializedValue(const std::string& data) {
    std::string buffer(data);
    const First& value = *reinterpret_cast<const First*>(buffer.data());
    buffer.erase(sizeof(First));
    return std::tuple<First>(value);
}

// 変数を一つずつ復元する関数
template<class First, class Second, class... Rest>
std::tuple<First, Second, Rest...> GetDeserializedValue(const std::string& data)
{
    std::string buffer(data);
    const First& value = *reinterpret_cast<const First*>(buffer.data());
    buffer.erase(sizeof(First));
    
    // 後続するテンプレート引数を使って再帰呼び出しをして、結果のタプルを連結する
    return std::tuple_cat(std::tuple<First>(value), GetDeserializedValue<Second, Rest...>(buffer));
}

閉鎖

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