2013-03-29 27 views
5

hemen hemen aynı kodu tekrar etmek Makro, gibi bir şey:Ben derleme zamanı sabiti parametreye bağlıdır aynı kodu yazmak zorunda

map["text 0"] = vec[0]; 
map["text 1"] = vec[1]; 
... 
map["text n"] = vec[n]; 

Sorun kod yazıyorum ben n bilmiyorum ki Bunu şablon parametresi olarak aldım. Açık çözüm bir döngü kullanmak ve döngü içinde "text k" oluşturmak ve vec[k] kullanın, ancak bu derleme zamanında yapılması gerektiğinde çalışma zamanı yükü vardır. Başka bir çözüm farklı N değerleri için fonksiyon uzmanlaşmak olurdu, ama bu şekilde aynı kodu elle birden fazla kez yazmam gerekecek ve şablon yapmak için bir neden yok.

N kere (BOOST_PP_REPEAT makro ailesi gibi) benzer şeyleri tekrarlayabilen bazı akıllı makrolar olduğunu biliyorum, ancak özel sorunum için bir çözüm bulamıyorum.

Bu sorun için herhangi bir çözüm var mı?

+0

uygulamaya etti: tekrarlama sorunu (denenmemiş) aşağıdaki teknikle birlikte çözülebilir? – jrok

+0

@jrok Evet, fakat tüm özellikleri (VS2010 ve en yeni Xcode) – Felics

+0

Şablonlar ve bir döngü muhtemelen derleyici tarafından optimize edilmiş olabilir. –

cevap

4

Gerçekten, gerçekten sıkı performans kısıtlamaları olmadıkça, çalışma zamanı yükü hakkında endişelenmenize gerek yok. Eklemeler her zaman çalışma zamanında gerçekleştirilecek ve ekleme zamanı kesinlikle bir dizgede bir karakteri değiştirmek için gereken süreye hakim olacak. Makrolar hata ayıklamak ve korumak için çok zor: Mümkünse bunları önlemek.

std::string const s = "text "; 
std::map<std::string, int> m; 
for (int i = 0; i < N; i++) 
{ 
    m[s + std::to_string(i)] = vec[i]; 
} 
: Rakamlarınız bir dizeye bir tamsayı dönüştürmek için to_string() işlevini kullanabilirsiniz C++ 11'de, daha yüksek 9 büyürse

std::string s = "text 0"; 
std::map<std::string, int> m; 
for (int i = 0; i < N; i++) 
{ 
    m[s] = vec[i]; 
    s[5] = '1' + i; // This is going to be the run-time overhead... 
} 

: Burada, bir basit döngü göz önüne sermek için öneririm

Performans, numaralı bir sorun olduğunu kanıtlarsa, makrolara dayalı daha sert bir yaklaşım deneyebilirsiniz. Ancak, ölçümleriniz önemli bir ek yük göstermezse, sadeliği ve açıklığı tercih eder ve basit bir döngüyü açar.

+0

Bu, tanımlanmamış davranışları tetikleyecektir, const karakterini değiştiremiyorum * - "text 0", const olarak bildirilmese bile const char *. – Felics

+1

@Felics: "lite 0" dizesi değişkeni, 'const char []' türüne sahiptir, ancak değiştirilebilen "char" dizisini başlatmak için kullandığınız şey budur. Orijinal edebi değiştirmiyorsunuz, bu yüzden burada UB yok. Ve eğer deseniniz daha karmaşıksa, 'std :: string' kullanabilirsiniz. –

+0

Olumsuz olarak bildirmiş olsanız bile, const'dan const olmayanlara (2011 standardında kabul edilen, 2011 standardına göre kabul edilmeyen) bir dönüşüm var. Ayrıca N birden fazla sayıya sahip olabilir. – Felics

0

Ben şu çalışması gerekir inanıyoruz: if() bir şablon parametresi (n) bir edebi karşılaştırır, böylece herhangi optimizasyoncusu değerinde onun tuzu bu şubesiz kod oluşturur

#include <boost/preprocessor.hpp> 
//... or just the required sub-headers 

// Will generate code for 0, 1, ... (N_END - 1) 
#define N_END 10 

#define ONE_ASSIGNMENT(maZ, maIter, maData) \ 
    if (maIter <= n) map["text " BOOST_PP_STRINGIZE(maIter)] = vec[maIter]; 

BOOST_PP_REPEAT(N_END, ONE_ASSIGNMENT, %%) //this generates the code 

#undef ONE_ASSIGNMENT 
#undef N_END 

Not söyledi.

%%'u "bu değer hiçbir zaman kullanılmaz" olarak kullanıyorum. Bu, maData bağımsız değişkenine aktarıldı, bu nedenle gerçekten geçmek için yararlı bir şeyiniz varsa ("text " gibi), bunun yerine bunu yapabilirsiniz.

+0

"n" şablon parametresi olarak alındığını unutmayın ... –

+0

@MatthieuM. Evet. Bu iyi. Buna rağmen, iyimserlerin 'if() 'ı sadece bedene ya da' nop 'haline getirmesi için buna güveniyorum, çünkü hem edebi (' maIter ') hem de derleme zamanı sabiti (' n') içerdiğini biliyor durumda. Tabii ki, kod optimizasyon olmadan da çalışırdı (ama gerçekten sadece derleme zamanı koşulunun ortadan kaldırılması). – Angew

+0

O zaman neden tam olarak anlamıyorum ki <= n', o = n n değil mi? (Ben anwyay soru anladım emin değilim ...) –

0

Tekrarlama benim için bir sorun gibi görünmüyor, ancak int'nin dize ve sonraki birleştirme işleminin derleme zamanı dönüştürmesi yapılıyor. Eğer C++ 11 kullanabilir miyim

template<k,l> struct fill_vector { 
    static void doIt (... & vec) { 
     vec [INT_TO_TEXT (k)] = k; 
     fill_vector<k+1,l-1>::doIt (vec); 
    } 
}; 

template<k> struct fill_vector<k,0> { 
    static void doIt (... & vec) { 
     vec [INT_TO_TEXT (k)] = k; 
    } 
}; 

//... 

fill_vector<0,n>::doIt (vec); 

Belki birileri bir fikir nasıl INT_TO_TEXT

İlgili konular