3

だから、私は本当に次のようなものを書きたいC ++でこの種のものに数回遭遇しました

case (a,b,c,d) of
     (true, true, _, _ )     => expr
   | (false, true, _, false) => expr
   | ...

しかし、C++ では、必ず次のような結果になります。

bool c11 = color1.count(e.first)>0;
bool c21 = color2.count(e.first)>0;
bool c12 = color1.count(e.second)>0;
bool c22 = color2.count(e.second)>0;
// no vertex in this edge is colored
// requeue
if( !(c11||c21||c12||c22) )
{
    edges.push(e);
}
// endpoints already same color
// failure condition
else if( (c11&&c12)||(c21&&c22) )
{
    results.push_back("NOT BICOLORABLE.");
    return true;
}
// nothing to do: nodes are already
// colored and different from one another
else if( (c11&&c22)||(c21&&c12) )
{
}
// first is c1, second is not set
else if( c11 && !(c12||c22) )
{
    color2.insert( e.second );
}
// first is c2, second is not set
else if( c21 && !(c12||c22) )
{
    color1.insert( e.second );
}
// first is not set, second is c1
else if( !(c11||c21) && c12 )
{
    color2.insert( e.first );
}
// first is not set, second is c2
else if( !(c11||c21) && c22 )
{
    color1.insert( e.first );
}
else
{
    std::cout << "Something went wrong.\n";
}

特にエラーが発生しやすいように思われるため、これらすべての if と else をクリーンアップする方法があるかどうか疑問に思っています。case 式 (または C++ のステートメント) が網羅的でない場合に、SML が行うように、コンパイラに文句を言わせることができれば、さらに良いでしょう。この質問は少し漠然としています。要するに、C++ で任意の数の変数を含む網羅的な真理値表をどのように表すのでしょうか? 前もって感謝します。

4

3 に答える 3

5

C++ は伝統的に個人向けであり、構文に関係なく、次のようなことはできません。

if ([a,b,c,d] == [true,true,false, false]) {}

新しい C++ 標準には、定数の配列をインラインで定義できるものがいくつかあるため、配列をコンストラクターとして取り、そのような比較をサポートするクラスを定義することができます。何かのようなもの

auto x = multi_val({a,b,c,d});
if (x == multi_val({true, true, false, false}))
{ ... }
else if (x == multi_val(etc.))

しかし、今では _ のような部分一致を行うには、それは直接サポートされておらず、おそらくテンプレート型を使用して行くなど、クラスをさらに複雑にしてそれをごまかす必要があります

multi_val(true, true, maybe<bool>(), maybe<bool>)

これはかなり頭の痛い C++ の領域に入ります。

于 2012-08-30T20:53:06.957 に答える
2

C++ 11 の場合、固定数のブール値のみに一致させたいと仮定し、_ パターン マッチングなしで存続できると仮定すると、[1] (必要な変数の数に拡張)。

私はまだ、テンプレートを使用して式にラムダまたはファンクターを使用して任意の型に一致させる代替ソリューションに取り組んでいます。

-編集-

約束どおり、[2] 任意の型のパターン マッチング。不特定の値。

いくつかの注意事項に注意してください。

  1. このコードは 4 つの変数でのみ機能します (実際、テンプレート メタプログラミングへの私の最初の進出です)。これは、可変個引数テンプレートを使用すると大幅に改善される可能性があります。
  2. 機能しますが、あまり整頓されていないか、よく整理されていません。実稼働コードに導入する前にクリーンアップする必要がある概念実証。
  3. マッチ機能に満足していません。初期化子リストを使用して、評価する式を渡し、最初の一致で停止することを望んでいました (現在の実装では、一致するすべての条件が実行されます) - しかし、異なる型のオブジェクトに一致する式を渡す方法をすぐに考えることができませんでした単一の初期化子リストを介して。

真理値表が網羅的であることを検証する方法が思いつきません。

乾杯、

-ニック

[1]

constexpr int match(bool v, int c)
{
    return v ? (1 << c) : 0;
}
constexpr int match(bool a, bool b)
{
    return match(a, 0) | match(b, 1);
}

int main()
{
    int a = true;
    int b = false;

    switch(match(a, b))
    {
        case match(false, false):
            break;
        case match(false, true):
            break;
        case match(true, false):
            break;
        case match(true, true):
            break;
    }

}

[2]

template<typename V1, typename V2, typename V3, typename V4>
class pattern_match_t
{
private:
    V1 value_0;
    V2 value_1;
    V3 value_2;
    V4 value_3;
public:
    typedef std::function<void(V1, V2, V3, V4)> expr_fn;

    template <typename C1, typename C2, typename C3, typename C4>
    pattern_match_t<V1, V2, V3, V4>& match(C1 a, C2 b, C3 c, C4 d, expr_fn fn)
    {
        if(value_0 == a && value_1 == b && value_2 == c && value_3 == d)
            fn(value_0, value_1, value_2, value_3);
        return *this;
    }

    pattern_match_t(V1 a, V2 b, V3 c, V4 d)
     : value_0(a), value_1(b), value_2(c), value_3(d)
    {
    }
};

template<typename T>
class unspecified
{};

template<typename T>
constexpr bool operator==(unspecified<T>, const T&)
{
    return true;
}

template<typename T>
constexpr bool operator==(const T&, unspecified<T>)
{
    return true;
}

template<typename V1, typename V2, typename V3, typename V4>
pattern_match_t<V1, V2, V3, V4> pattern_match(V1 a, V2 b, V3 c, V4 d)
{
    return pattern_match_t<V1, V2, V3, V4>(a, b, c, d);
}

int main()
{

    bool test_a = true;
    std::string test_b = "some value";
    bool test_c = false;
    bool test_d = true;

    pattern_match(test_a, test_b, test_c, test_d)
        .match(true, unspecified<std::string>(), false, true, [](bool, std::string, bool, bool)
        {
            return;
        })
        .match(true, "some value", false, true, [](bool, std::string, bool, bool)
        {
            return;
        });
}
于 2012-08-31T23:36:16.153 に答える