(C++11)テンプレート使用時の primary-expression token なビルドエラー対応方法メモ Edit

C++11のテンプレートメソッド内で別のテンプレートを呼び出している箇所で、特定のコンパイラでコンパイル時に

error: expected primary-expression before '>' token

なエラーが出た場合の解決方法メモです。

// テンプレートなクラス
template<typename T1>
class TemplateClass
{
public:
	template<typename T2> T2 func() { return T2(); }
};

// テンプレートな関数
template<typename T1, typename T2>
void templateFunction()
{
	TemplateClass<T1>	t;
	t.func<T2>();		// < ここでエラーがでます
}

// templateFunctionをコール
void main()
{
	templateFunction<int,float>();
}

上記のコードをビルドするとこんなエラーが出ます。

hoge.cpp: In function 'void templateFunction()':
hoge.cpp:xxx:xxx: error: expected primary-expression before '>' token
   t.func<T2>();
            ^
hoge.cpp:xxx:xxx: error: expected primary-expression before ')' token
   t.func<T2>();
              ^

templateFunction()内の

t.func<T2>();

を以下のように書き換えるとビルドエラーが解消されます。

t.template func<T2>();

参考
http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords

staticなメンバ変数の初期化 Edit

Hoge.h

class Hoge {
public:
	static func();
private:
	static std::vector<int>	m_vector;
	static std::bitset<16>	m_bitset;
	static int		m_array[16];
};

Hoge.cpp

Hoge::func()
{
	m_vector.clear();
	m_bitset.reset();
	m_array[0] = 0;
}

という風にしてしまうと、LNK2001の外部参照が未解決リンクエラーが出てしまいます。
staticなメンバ変数は、ヘッダ上では宣言しているだけなので、実体の確保はソース(cpp)側で行う必要があります。
Hoge.cppのfunc()の前に

std::vector<int>	Hoge::m_vector;
std::bitset<16>	Hoge::m_bitset;
int			Hoge::m_array[16];

を追記して、暗黙の初期化を行うようにすればリンクエラーは解消されます。

クラスのメンバ関数ポインタをアップキャストして使用する Edit

宣言部

class FuncClassBase;
typedef void			(FuncClassBase::*FuncClassCallback)();
class FuncClassBase {
public:
	FuncClassCallback	m_callback;
};
 
class FuncClassA : public FuncClassBase {
	int		a;
public:
	FuncClassA()
	{
		a = 99;
	}
	void			funcA()
	{
		printf( "funcA %d\n", a );
	}
};

実装部

FuncClassBase	funcClassBase;
FuncClassA	funcClassA;

// static_castすればFuncClassBaseの関数ポインタ型のFuncClassCallbackにFuncClassAの関数ポインタを代入する事ができる
FuncClassCallback fc = static_cast<FuncClassCallback>(&FuncClassA::funcA);

(funcClassA.*fc)(); // これは安全
(funcClassBase.*fc)(); // これは危険。やっちゃだめ

// このやり方も大丈夫
funcClassA.m_callback = static_cast<FuncClassCallback>(&FuncClassA::funcA);
(funcClassA.*funcClassA.m_callback)();

クラスのメンバ関数ポインタのエラーに関するメモ Edit

class Hoge
{
public:
	void	(Hoge::*m_func)(void);
	void Call()
	{
		this->m_func = &Hoge::Func;

		(this->*m_func)();
	}
	void Func(void)
	{
		printf("func\n");
	}
};

下記のエラーは

error C3867: 'Hoge::Func': function call missing argument list; use '&Hoge::Func' to create a pointer to member

こうやると、

this->m_func = Func;

出るエラーなので、

this->m_func = &Hoge::Func;

こうする。

templateクラス内templateクラスのstaticメンバ変数を初期化する Edit

templateクラス内のtemplateクラスのstaticメンバ変数に初期値を入れたい場合、

template <typename T1>
class Hoge1
{
  template< typename T2 >
  class Hoge2
  {
     static int id_; // これを初期化したい時
  };
};

↓こんな風に書けば初期値を入れられる。

template<typename T1>
template<typename T2>
int Hoge1<T1>::Hoge2<T2>::id_ = (sizeof(T1) * sizeof(T2));

オペレータ Edit

TIPS Edit

  • イテレータのforループでは前置インクリメントを使用する
    for (it=v.begin(); it!=v.end(); it++) {}
    より
    for (it=v.begin(); it!=v.end(); ++it) {}
    の方が、速度、メモリ効率が良い。
    http://d.hatena.ne.jp/cubicdaiya/20080606/1212695409
    http://ch.cri-mw.co.jp/hirase/275.html
  • c#みたいに #region でコードを折りたたみたい場合は #pragma region を使う。
    #pragma region 折りたたみ
    // ここが折りたたまれます。
    int a = 10;
    a = 20;
    #pragma endregion
  • 警告
    warning C4311: '型キャスト' : ポインタを 'void *' から 'unsigned int' へ切り詰めます。
    64bit環境で問題が起きます。
    1.uintptr_tのような移植可能な型を利用する
    2./Wp64オプション(構成プロパティ - C/C++ - 全般 - 64 ビット移植への対応)を指定しない(いいえにする)
    のどちらかで対応可能です。
  • __DATE__とか__TIME__とか__FILE__とか__LINE__とかをワイド文字列にする。
     const wchar_t* s = __DATE__;
    としようとするとコンパイルエラーになってしまう。
    以下のようなマクロを使うとうまくいく。
     #define WIDEN2(x) L ## x
     #define WIDEN(x) WIDEN2(x)
     const wchar_t* s = WIDEN(__DATE__);
    参考サイト
    http://msdn.microsoft.com/en-us/library/b0084kay%28v=vs.80%29.aspx

リロード   新規 編集 凍結 差分 添付 複製 名前変更   ホーム 一覧 単語検索 最終更新 バックアップ リンク元   ヘルプ   最終更新のRSS
Last-modified: 2014-03-18 (火) 14:45:58 (1193d)