NEW:これを手伝ってくれてありがとう皆さん!その答えは、以下のマークされ、私は私の質問で機能バージョンと答えに拡大してきた、(QV)以下:テンプレートと文字列リテラルとユニコード
私たちの文字列ユーティリティを更新している間、私は(このような状況の中に多くのことを実行しているように見えますライブラリ):
さまざまな文字列リテラルを使用するcharとwchar_tの両方で動作するテンプレートを用意する方法が必要です。コンパイル時に文字列リテラルを狭くするかワイド文字にするかを知りません。すぐに我々は '"'(2つの文字列リテラルに問題がある
// quote the given string in-place using the given quote character
template <typename CSTRING_T, typename CHAR_T>
inline void MakeQuoted(CSTRING_T & str, CHAR_T chQuote = '"')
{
if (str.IsEmpty() || str[0] != chQuote)
str.Format("%c%s%c", chQuote, str, chQuote);
}
、:
// quote the given string in-place using the given quote character
inline void MakeQuoted(CString & str, TCHAR chQuote = _T('"'))
{
if (str.IsEmpty() || str[0] != chQuote)
str.Format(_T("%c%s%c"), chQuote, str, chQuote);
}
は、私が代わりにそれをテンプレートにしたい:
は検討のために、以下のTCHARベースの機能を取ります"%c%s%c")。
上記のCSTRING_T = CStringA、CHAR_T = charの場合は上記のリテラルは問題ありませんが、CStringWとwchar_tで呼び出された場合はy必要(L '' '、L "%c%c%c")。
だから私のようなものを行うにいくつかの方法が必要です。
template <typename CSTRING_T, typename CHAR_T>
inline void MakeQuoted(CSTRING_T & str, CHAR_T chQuote = Literal<CHAR_T>('"'))
{
if (str.IsEmpty() || str[0] != chQuote)
str.Format(Literal<CHAR_T>("%c%s%c"), chQuote, str, chQuote);
}
を私が失われていますところそれはです:世界で私はリテラル(文字列または文字リテラル)を作るために何ができるか、実際の結果L "文字列"または "文字列"に応じてCHAR_T?
編集:100以上の関数がありますが、その中にはより多くの複雑な文字列リテラルがあり、幅の狭い文字列と幅広い文字列の両方で使用できる必要があります。そのような関数をすべてコピーしておき、それぞれを幅広くまたは狭く編集するのではなく、確かにCHAR_Tごとに異なる単一の定義を許可するテクニックがありますか?
私はマーク身代金を与え、私は(世話を誰のため)、より完全なソリューションを含めたかったので、ここにあるハイブリッドマクロ+テンプレートに答えを与えている:
// we supply a few helper constructs to make templates easier to write
// this is sort of the dark underbelly of template writing
// to help make the c++ compiler slightly less obnoxious
// generates the narrow or wide character literal depending on T
// usage: LITERAL(charT, "literal text") or LITERAL(charT, 'c')
#define LITERAL(T,x) template_details::literal_traits<typename T>::choose(x, L##x)
namespace template_details {
// Literal Traits uses template specialization to achieve templated narrow or wide character literals for templates
// the idea came from me (Steven S. Wolf), and the implementation from Mark Ransom on stackoverflow (http://stackoverflow.com/questions/4261673/templates-and-string-literals-and-unicode)
template<typename T>
struct literal_traits
{
typedef char char_type;
static const char * choose(const char * narrow, const wchar_t * wide) { return narrow; }
static char choose(const char narrow, const wchar_t wide) { return narrow; }
};
template<>
struct literal_traits<wchar_t>
{
typedef wchar_t char_type;
static const wchar_t * choose(const char * narrow, const wchar_t * wide) { return wide; }
static wchar_t choose(const char narrow, const wchar_t wide) { return wide; }
};
} // template_details
はまた、私は&理解を読み取るためにCStringT <と一緒にこの概念を利用筆記テンプレート>少し簡単に/よりよいを作るために、いくつかのヘルパーを作成しました:
// generates the correct CString type based on char_T
template <typename charT>
struct cstring_type
{
// typedef CStringT< charT, ATL::StrTraitATL< charT, ATL::ChTraitsCRT<charT> > > type;
// generate a compile time error if we're invoked on a charT that doesn't make sense
};
template <>
struct cstring_type<char>
{
typedef CStringA type;
};
template <>
struct cstring_type<wchar_t>
{
typedef CStringW type;
};
#define CSTRINGTYPE(T) typename cstring_type<T>::type
// returns an instance of a CStringA or CStringW based on the given char_T
template <typename charT>
inline CSTRINGTYPE(charT) make_cstring(const charT * psz)
{
return psz;
}
// generates the character type of a given CStringT<>
#define CSTRINGCHAR(T) typename T::XCHAR
上記では、CStringT <>またはchar/wchar_t引数に基づいて、正しいCStringの種類を生成するテンプレートを記述することができます。例えば:私はあなたがTEXT
MFCマクロをしたいと考えてい
// quote the given string in-place using the given quote character
template <typename cstringT>
inline void MakeQuoted(cstringT & str, CSTRINGCHAR(cstringT) chQuote = LITERAL(CSTRINGCHAR(cstringT), '"'))
{
if (str.IsEmpty() || str[0] != chQuote)
str.Format(LITERAL(cstringT::XCHAR, "%c%s%c"), chQuote, str, chQuote);
}
// return a quoted version of the given string
template <typename cstringT>
inline cstringT GetQuoted(cstringT str, CSTRINGCHAR(cstringT) chQuote = LITERAL(CSTRINGCHAR(cstringT), '"'))
{
MakeQuoted(str, chQuote);
return str;
}
私は、関数のオーバーロードを使って、単一のテンプレートを使うのではなく、MakeQuotedの2つの定義を生成できることに気付いています。その時点で、リテラルについて心配する必要はありません(@In silicoの答えは以下を参照してください)。しかし、それは、リテラルの2つの異なるセットを供給するだけで、すべてのコードをそのまま繰り返していることを考えると、ばかげているようです。確かに、正確なリテラル(タイプ依存のリテラル)をオンザフライで生成するためにメタプログラミングを使用する方法がいくつかあります。 – Mordachai
@Mordachai:メタプログラミングを使用していません。もしあれば、文字列を切り替えることもできます。この関数を*使用するために使用したい構文の例を挙げることができますか? –
これが当てはまるかどうかはわかりません。テンプレートは、テンプレートに提供される型パラメータに基づいて変化するコードを生成します。私がここで探しているのは、それに供給される型によって異なるリテラルです。たぶんテンプレートの専門性?それは、コンパイラが文字列リテラルの自動型宣伝をしたいようなものです(スカラーリテラルは適切な型に自動的に昇格されるため、テンプレートは努力なしで動作しますが、文字列リテラルではそうではありません)。 : – Mordachai