実際のコードはより複雑ですが、この例に減らすことができました。アプリケーションをリンクするためのこの時点でテンプレートstatic constexpr odr-used変数の定義
私はMyPackets_tへのポインタを取るしようとするまで、すべてが正常に動作します::タイプ(メインでfooへのコメントを解除コール()())
、種類は定義が必要です。
私は定義の正しい構文に苦しんでいます。テンプレートをコメントアウト...トリックを行う必要があります。しかし、 "PacketCollection :: types 'へのテンプレート引数は元のテンプレートと一致しません"というエラーを発生させます。
このようなものを試してみてください - テンプレート<> constexpr int PacketCollection :: types []; - 変数が宣言されているのではなくその行で使用されているかのように、別のリンカーエラーを引き起こします。
私は、PacketCollectionの代わりにMyPackets_tを使用しようとしました - 同じ結果。
私がパケットをテンプレート化しないと、すべてがコンパイルされ、期待どおりに実行されます。
私はここで非常に基本的なものがないか、コンパイラにバグがあります。私はgcc 4.8と4.9でこの動作を得ています。
Clang 3.5は、状況によってはsligtly異なるテイクを持っています:constexprの静的データの宣言 'types'はイニシャライザを必要とします。
私がこれまでに見つけた唯一の回避策は、代わりに
static constexpr std::array<int, 2> types() { return {1,2}; }
を使用していたが、私はこのソリューションを好きではありません。変数がテンプレート化されていないバージョン(ヘッダーのイニシャライザを使用)で動作する場合、テンプレート化されたバージョンでも動作するはずです。
#include <iostream>
using namespace std;
class Packet_A
{
public:
static constexpr int TYPE = 1;
};
class Packet_B
{
public:
static constexpr int TYPE = 2;
};
template <typename T> class PacketCollection
{
public:
static constexpr size_t size = 2;
static constexpr int types[size] { 1, 2 };
};
typedef PacketCollection<Packet_A> MyPackets_t;
//template<typename T> constexpr int PacketCollection<Packet_A>::types[PacketCollection<Packet_A>::size];
void foo(const int* bar, size_t size)
{
if (size >= 2)
{
cout << bar[0] << bar[1];
}
}
int main(int argc, char* argv[])
{
cout << Packet_A::TYPE;
cout << MyPackets_t::types[0];
//foo(MyPackets_t::types, MyPackets_t::size);
return 0;
}
ありがとうございました!これはうまくいった。なぜ、どのように動作するのかを説明する仕様セクションはありますか? – Ghostrider
@Ghostrider [draft standard](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf)の[temp.static]/1: 'テンプレートクラスX { 静的T s; }; テンプレート T X :: s = 0; ' –
TemplateRex