2010-12-09 20 views
7

Bir enum'un belirtilen değerlerin bir değerinin olup olmadığını kontrol etmenizi sağlayan hızlı/anında bir senkronizasyon garipliği yolu var mı?Enum değerlerini kontrol etmenin hızlı yolu

Örnek:

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
} 

int main() 
{ 
    fruit_and_vegetables something = apples; 
    if(something = {apples, pears}) // <-- this here 
     cout << "something is fruit." << endl; 
    else 
     cout "something is a vegetable." << endl; 
    return 0; 
} 

teşekkürler!

+2

Domates ve salatalık * olan * –

+0

Scotus'a göre değil ;-p meyve: http://en.wikipedia.org/wiki/Tomato#Fruit_or_vegetable.3F –

+0

@Noah: 'domates' * ve domates değil * – ruslik

cevap

4

Ah, bu yapılabilir oldukça kolay...

template <typename T> 
pair<T, fruit_and_vegetables> operator||(T t, fruit_and_vegetables v) { 
    return make_pair(t, v); 
} 

template <typename T> 
bool operator==(fruit_and vegetables lhs, pair<T, fruit_and_vegetables> rhs) { 
    return lhs == rhs.second || lhs == rhs.first; 
} 

Bu

sonra şöyle kullanılabilir:

if (something == (apple || pear || orange)) eat_the_yummy_fruit(something); 
else feed_to_rabbit(something) 

ama (apple || (pear || orange)) yaparsanız çalışmaz. Bu kolayca düzeltilebilir, ancak kodu basit tutmak istedim. Bence bu, şu ana kadarki en büyük cevap olan tek cevabın ...

+0

Büyük aralıklar da üretmenin bir yolu var mıydı? Bu tamamen ilgisiz olurdu, çözümünüz mükemmel bir şekilde istediğimi yapmamı sağlıyor! Teşekkürler. – rubenvb

4

if (something < tomatoes)...

+1

Ah evet, “Neden bunu düşünmedim” (C) '… ama eğer enum ara değerlere sahipse ve benim örneğim daha karmaşık/kararsız hale gelirse? Domateslerin lezzetli olduğunu iddia etmek için – rubenvb

5

ben farkındayım, ama ne yapabilirim atadığınız değerleri enum üyelerine 2^i olduğunu değil. Örneğin:

enum fruit_and_vegetables 
{ 
    apples = (1<<0), 
    pears  = (1<<1), 
    tomatoes = (1<<2), 
    cucumbers = (1<<3) 
    // ... 
} 

Sonra Elbette

if (something & (apples | pears | tomatoes)) 
    std::cout << "is tasty" << std::endl; 

ile kontrol edebilirsiniz, bu makul bir boyutu ile çeteleler ile sınırlıdır (Ben en fazla 32 öğeye sahip olabilir düşünüyorum). Birden fazla 32 (64) değerleri varsa

DÜZENLEME

, bu daha yaratıcı olmak zorunda.

enum fruit_and_vegetables { 
    apples = 1, //! 
    pears, 
    tomatoes, 
    cucumbers, 
    // ... 
    grapes 
} 
#define FRUIT_AND_VEGETABLES 120 

if ( (1<<something)  & ((1<<apples) | (1<<pears) | (1<<tomatoes)) 
    || (1<<(something-32) & ((1<<(apples-32)) | (1<<(pears-32)) | (1<<(tomatoes-32)))) 
    || ...) { 
    std::cout << "my keyboard is broken, but tastes good" << std::endl; 
} 

Ama bu gerçekten harika bir çözüm değildir: çeşitli denetim yaparak, hala oldukça hızlı olabilir. Çok sayıda enumanız varsa ve bunlar birkaç sınıfa ayrılabilirlerse, Noah Roberts' answer ile giderdim. Başka bir yolu yoktur

+1

-1! j/k Buna rağmen, enumdan bu tür davranışlar istemeye başladığınız zaman, bir enum, istediğiniz davranış için uygun bir yapı değildir. –

+2

Şaka yapıyor olmalısın! Domatesler harika. – bitmask

+2

@bitmask: Enum 70 üye içeriyorsa? Bu leftshift yaklaşımı işe yaramaz! – Nawaz

1

, o @bitmask cevabını uzatır:

Eğer kontrol edebilir kriterlerin sabit vardır varsayalım.

enum fruit_and_vegetables { 
    apples = 0, 
    pears, 
    tomatoes, 
    cucumbers 
} 

enum qualifs { 
    is_fruit = 1, 
    is_sweet = 1<<1, 
    is_round = 1<<2, 
    is_tasty = 1<<3 
} 

const qualifs qualifs_LUT[] = { // can be generated 
    is_fruit | is_sweet | is_round, // apple 
    ... 
}; 

böylece belirli bir eleme irade kontrol

if (qualifs_LUT[tomato] & is_tasty) 
haline geldiğini: Öyleyse fruit_and_vegetables enum değerleri için bit maskesi kullanmak yerine, ek LUT kullanabilirsiniz (o kelimenin boyutuna sınırlayacaktır)

EDIT: ve başka bir ilginç yöntem. @bitmask: yöntemini tekrar düşünün. 2'nin güçlerine dayanıyor. Ama ne kadar primes? numaralandırma değerlerine asal sayılar atayarak, daha fazla değer squize böylece Onlar o ürünü varsayarak, daha yavaş çok büyür olmaz taşma:

enum fruit_and_vegetables { 
    apples = 2, 
    pears = 3, 
    tomatoes = 5, 
    cucumbers = 7 
} 

if ((apples * pears * tomatoes) % tomatoes == 0) 
    printf("it's tasty!"); 

bu bir denetim kümesinde öğe sayısını sınırlamaktadır.

Sen istediğin sözdizimi ulaşmak için yardımcı olacaktır yardımcı şablonu yazabilir
+0

bunu seviyorum! (Ama muhtemelen lut 'const' yapmalısınız) – bitmask

+0

@bitmask: peki, bu sadece bir uygulama detayı :) – ruslik

+0

Biliyorum, ama 15 karakter doldurmalıydım :) – bitmask

1

:

enum fruit_and_vegetables 
{ 
    nothing, 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
}; 

// helper template 
typedef fruit_and_vegetables fav; 
template<fav v1 = nothing, fav v2 = nothing, fav v3 = nothing, fav v4 = nothing, 
    fav v5 = nothing, fav v6 = nothing, fav v7 = nothing, fav v8 = nothing> 
bool check_equal(fruit_and_vegetables value) 
{ 
    return (value == v1 || value == v2 || value == v3 || value == v4 || 
      value == v5 || value == v6 || value == v7 || value == v8); 
} 

// usage 
int main() 
{ 
    fruit_and_vegetables something = apples; 
    if(check_equal<apples, pears>(something)) 
     std::cout << "something is fruit." << std::endl; 
    else 
     std::cout << "something is a vegetable." << std::endl; 

    return 0; 
} 
+0

Her değeri elle kontrol etmekle aynı şey. OP, açık olandan daha hızlı bir yöntem istedi. – ruslik

+1

OP basit sözdizimi hakkında sordu: "synatx gariplik ineline yolu". –

1

büyük işlemek için ürünlerin sıralanmamış kümeleri:

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers, 
    MAX_VALUE 
}; 

vector<bool> arguablyVegetables(MAX_VALUE, false); 
arguablyVegetables[tomatoes] = true; 
arguablyVegetables[cucumbers] = true; 

cout << arguablyVegetables[apples] << endl; 
1

neden mantığını veya birkaç fruit_and_vegetables mantıksal değerini kullanmıyor? için Ölçekler iyi); Eğer operatör || ve operatöre önce == aşırı yükleri, yanı sıra argümanlar ve sonuç tipleri önce constexpr koyarsanız , sonra derleyici derleme zamanında kodunuzu (hayır çalışma zamanı havai) mümkünse değerlendirecek Daha büyük a || b || c || c enum aralıkları ve değerleri istediğiniz gibi parantez içine koyabilirsiniz.

#include <set> 
using std::set; 

enum fruit_and_vegetables 
{ 
    apples, 
    pears, 
    tomatoes, 
    cucumbers 
}; 

set<fruit_and_vegetables> operator||(fruit_and_vegetables left, fruit_and_vegetables right) { 
    set<fruit_and_vegetables> set; 
    set.insert(left); 
    set.insert(right); 
    return set; 
} 

set<fruit_and_vegetables> operator||(set<fruit_and_vegetables> left, fruit_and_vegetables right) { 
    left.insert(right); 
    return left; 
} 

set<fruit_and_vegetables> operator||(fruit_and_vegetables left, set<fruit_and_vegetables> right) { 
    right.insert(left); 
    return right; 
} 

bool operator!=(fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs) { 
    return (rhs.find(lhs) == rhs.end()); 
} 

bool operator==(fruit_and_vegetables lhs, set<fruit_and_vegetables> rhs) { 
    return !(lhs != rhs); 
} 

int main() { 

fruit_and_vegetables fav = apples; 
if (fav == (apples || (pears || tomatoes))) cout << "match apples\n"; 
fav = cucumbers; 
if (fav == ((apples || pears) || tomatoes)) cout << "Error! matched ghost cucumbers\n"; 
if (fav != apples) cout << "correct no match apples\n"; 
if (fav == cucumbers) cout << "default operator==(FaV, FaV) match\n"; 
if (fav == (pears || apples)) cout << "yummi\n"; 

return 0; 
} 
İlgili konular