http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2087.pdfで説明されているように、再帰的バリデーションテンプレートを使用してsprintf()
の代替案を書いています。私の目標は、ユーザー定義型のカスタムデータ型フォーマッタを簡単に追加できるようにすることです。例えば、基本的な実装は次のように見える場合:再帰的なバリデーショナルテンプレートを持つ関数の部分テンプレートの特殊化への代替
#include <iostream>
#include <sstream>
#include <wchar.h>
#include <stdexcept>
using std::wstring;
using std::wstringstream;
const wstring wsprintf(const wchar_t *s)
{
wstringstream outstream;
while(*s)
{
if (*s == L'%' && *++s != L'%')
throw std::runtime_error("invalid format string: missing arguments");
outstream << *s++;
}
return outstream.str();
}
template<typename T, typename... Args>
const wstring wsprintf(const wchar_t *s, const T& value, const Args&... args)
{
wstringstream outstream;
while(*s)
{
if(*s == L'%' && *++s != L'%')
{
outstream << value << wsprintf(++s, args...);
return outstream.str();
}
outstream << *s++;
}
throw std::runtime_error("extra arguments provided to wsprintf");
}
が、私は
template<typename... Args>
const wstring wsprintf<const Foo&>(const wchar_t *s, const Foo& foo, const Args&... args)
{
return wsprintf(s, foo.customDescription(), args...);
}
を書き込むことによって(
wstring
を返すメソッド
customDescription()
が含まれている、のは言わせ、)私のクラス
Foo
のためのフォーマッタを追加することができます
私は、これを行うことができるだろう。しかし
Foo bar;
wstring message = wsprintf("my foo tells me %s", bar);
、私はこのコードが一部であるため動作しません書いた方法http://www.gotw.ca/publications/mill17.htmで説明されているように、関数(PTSF)のテンプレート特殊化は許可されていません。
PTSFの代わりに、一般的に利用可能な2つの選択肢があります:
- 完全テンプレートの使用を排除し、オーバーロードされた関数を使用します。
- 関数の特殊な実装をラップするための静的クラスを作成します。
printf()
への再帰可変長引数テンプレートアプローチは、少なくとも1つのテンプレート引数(可変引数パラメータパック)を必要とするため
最初の選択肢は、実現可能ないないようです。私は第二の代替を実装しようとしたとき
、私はいくつかの構文エラー(コメントとしてインライン)に走った:
namespace wsprintf_impl {
struct wsprintf
{
static const wstring impl(const wchar_t *s)
{
wstringstream outstream;
while(*s)
{
if (*s == L'%' && *++s != L'%')
throw std::runtime_error("invalid format string: missing arguments");
outstream << *s++;
}
return outstream.str();
}
};
// ERROR: redefinition of 'wsprintf' as different kind of symbol
template< class T, class Args&... args >
struct wsprintf
{
static const wstring impl(const wchar_t *s, const T& value, const Args&... args)
{
wstringstream outstream;
while(*s)
{
if(*s == L'%' && *++s != L'%')
{
outstream << value << wsprintf::impl(++s, args...);
return outstream.str();
}
outstream << *s++;
}
throw std::runtime_error("extra arguments provided to wsprintf");
}
};
}
template< class T, class Args&... args >
wstring wsprintf(const wchar_t *s, const T& value, const Args&... args)
// ERROR: type 'const Args &' of function parameter pack does not contain any unexpanded parameter packs
// ERROR: declaration of 'args' shadows template parameter
{
return wsprintf_impl::wsprintf<T, args...>::impl(s, value, args...);
// ERROR: expected '>'
// ERROR: expected '(' for function-style cast or type construction
}
は、私はこれらのエラーを修正するかどうかはわかりません。何か案は?私は最初の正しい道にいますか?