2016-04-08 19 views
1

Gerçek kod daha karmaşıktır ancak bu örneğe indirgeyebildim. Ben bağlamak uygulama için sırayla Bu noktadatemplate odr-used değişkeninin statik constexpr tanımı

(ana() içinde() foo için yorumsuz çağrı) :: türlerini MyPackets_t bir gösterici almaya çalışın kadar

her şeyi iyi çalışır, türleri bir tanım gerektirir .

Tanım için doğru sözdizimi ile uğraşıyorum. Şablonu yorumladı ... hile yapmalı. Ancak bir "genelleme" şablon argümanları 'PacketCollection :: types' özgün şablonla eşleşmiyor ".

Böyle bir şey yapmaya çalışın - template <> constexpr int PacketCollection :: types []; - Değişkenden ziyade değişken olarak kullanıldığı gibi başka bir bağlayıcı hatası verir.

PacketCollection yerine aynı sonuçları MyPackets_t kullanmayı denedim.

Paket koleksiyonunu şablon oluşturmazsam, her şey beklendiği gibi derler ve çalışır.

Burada son derece basit bir şey eksik ya da derleyici bir hata olduğunu hissediyorum. Bu davranışı gcc 4.8 ve 4.9 ile elde ediyorum.

Clang 3.5'in durumu oldukça farklı bir şekilde ele alınmıştır: constexpr statik veri üyesi 'türleri' bildirimi bir başlatıcı gerektirir.

buldum tek geçici çözüm

bugüne kadar yerine
static constexpr std::array<int, 2> types() { return {1,2}; } 

kullanmaktı, ama bu çözüm sevmiyorum. Değişkeni olmayan bir sürümünde (başlıktan başlatıcıyı kullanarak) değişken çalışıyorsa, aynı zamanda bir şablon için de çalışmalıdır.

#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; 
} 

cevap

2

Sen live example Bkz T yerine

template<typename T> constexpr int PacketCollection<T>::types[PacketCollection<T>::size]; 
                ^      ^

Packet_A ait kullanmalıdır.

+0

Teşekkür ederiz! Bu çalıştı. Bunun neden ve nasıl çalıştığını açıklayan bir şartname bölümü var mı? – Ghostrider

+0

@Ghostrider Bkz. Ör. [temp.static]/1 [taslak Standart] 'dan (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4582.pdf):' şablon sınıfı X { statik T s; }; template T X :: s = 0; ' – TemplateRex

İlgili konular