2016-03-21 9 views
0

sabit bir dize ilişkilendirmek için makro C++ 11:C11/Zaten bu şekilde yazılmış bir logger işlevine çağrıları içeren C++ kaynak kodu dosyalarının büyük bir set var bir hazır tamsayı

LogIx(_S("This is my msg")); 

:

#define _S(a) (#a) 

çalıştığını ama benim müşteri üretiminde kolayca anlaşılabilir bir logger (ı ... Neyse bu kadar katılıyorum ama yok) koymak istiyorum. Kaynak kodu tabanı çok büyüktür, bu yüzden benim fikrim mümkün olduğunca az değişiklik yapmak ve her mesaja bir sayı (indeks) ilişkilendirmek ve tüm mesajları bir tablonun içine koymak, böylece sayının tablodaki mesajın indeksi olması.

İlk fikir (işleyen) _S (...) iletilerinin tümünü bulur, bunları kaynaktan çıkarır ve bir benzerini eşdeğerleriyle doldurur ve ardından her _S() içindeki parametreyi enum etiketi ile değiştirir. Tabii ki bu hata eğilimli ve gelecekte başka mesajlar eklemek için çok iyi değil düşünüyorum.

Bu yüzden ön yordamı kullanan farklı bir çözüm düşünmekteyim, ancak #define'de alıntı yapılmış bir dizenin kullanılması mümkün görünmüyor.

çalışmak ama yapacak ne istiyorsunuz göstermiyor C++ kaynak Bu kod parçası:

#define _V(a) (#a) 

const std::array<string, 3> s_logStrings = { 
     _V("This is my msg"), 
     _V("Param %s is: %d"), 
     _V("Reset msg") 
}; 

#define _S("This is my msg") 0 
#define _S("Param %s is: %d") 1 
#define _S("Reset msg")  2 

int Log(size_t msgIndex) 
{ 
    cout << s_logStrings.at(LogIx(msgIndex)); 
} 

int main(void) 
{ 
    std::cout << "Begin test" << std::endl; 
    Log(_S("This is my msg")); 
    std::cout << "End test" << std::endl; 

    return 0; 
} 

#define _V(a) (#a) 

const std::array<string, 3> s_logStrings = { 
     _V("This is my msg"), 
     _V("Param %s is: %d"), 
     _V("Reset msg") 
}; 

#define _S(a) // ???? this is the problem... how define this macro? 
// also a constexpr could be a good solution, the point is to don't 
// add a function or a <map> 

#define _S("This is my msg") 0 
#define _S("Param %s is: %d") 1 
#define _S("Reset msg")  2 

int Log(size_t msgIndex) 
{ 
    cout << s_logStrings.at(msgIndex); 
} 

int main(void) 
{ 
    std::cout << "Begin test" << std::endl; 
    Log(_S("This is my msg")); 
    std::cout << "End test" << std::endl; 

    return 0; 
} 

herhangi bir fikir veya öneri takdir edilecektir. sizin literal açarak

+1

Not o 'büyük harfle (' _S' ve ardından bir alt çizgi ile başlar isimler _V') ve iki ardışık alt çizgi içeren isimler uygulamaya ayrılmıştır. Onları kullanma. –

cevap

0

char_sequence olarak, gibi bir şey yapabilir yazın:

template <char ... > struct char_sequence {}; 

// use gnu extension :/ 
template<class CharT, CharT... cs> 
char_sequence<cs...> operator ""_seq(){ 
    return {}; 
} 

template <class T, class Tuple> 
struct index_in_tuple; 

template <class T, class... Types> 
struct index_in_tuple<T, std::tuple<T, Types...>> { 
    static const std::size_t value = 0; 
}; 

template <class T, class U, class... Types> 
struct index_in_tuple<T, std::tuple<U, Types...>> { 
    static const std::size_t value = 1 + index_in_tuple<T, std::tuple<Types...>>::value; 
}; 

using MyMessagesTuple = decltype(std::make_tuple(
    "This is my msg"_seq, 
    "Param %s is: %d"_seq, 
    "Reset msg"_seq 
)); 


#define _S(a) (index_in_tuple<decltype(a##_seq), MyMessagesTuple>::value) 

int main() { 
    auto foo = _S("Reset msg"); 
    std::cout << foo << std::endl; 
} 

Demo