13

文字列リテラルではないものに対して確実に static_assert するにはどうすればよいですか?

たとえば、次のコードでは、標準の assert マクロをラップしようとしましたが、文字列リテラル以外のメッセージを静的に拒否しました (文字列リテラル以外は、アサートがトリガーされたときに実行時に表示されないため)。

#include <cassert>
#include <string>
#include <type_traits>

#define my_assert(test, message)\
    static_assert(\
        (\
            !std::is_pointer<decltype(message)>::value &&\
            !std::is_array<decltype(message)>::value\
        ),\
        "literal string required"\
    );\
    assert((message, (test)));

int main() {
    my_assert(1 == 1, "one equals one");
    my_assert(1 == 2, "one equals two");

    {
        const char *msg = "one equals one";
        //my_assert(1 == 1, msg); // triggers static_assert
    }

    {
        const char msg[] = "one equals one";
        //my_assert(1 == 1, msg); // triggers static_assert
    }

    {
        const std::string msg = "one equals one";
        //my_assert(1 == 1, msg.c_str()); // triggers static_assert
    }

    {
        const int msg = 3;
        my_assert(1 == 1, msg); // should trigger static_assert
    }
}

ご覧のとおり、テストは type_traits ヘッダーによって提供されるテストを介して行われ、 ほとんどの場合、このコードは意図したとおりに動作します (gcc 4.7.2 でテスト済み)。ただし、プログラマーが適切に使用する可能性のある一般的なものを拒否するだけなので、特に文字列リテラルを探すわけではありません。

私が持っている解決策は、上記の例には十分かもしれませんが、これ、または他の状況でも同様の手法を使用したいと思います。

問題は、type_traits (または別の標準メカニズム) を確実に使用して、文字列リテラル以外のstatic_assertを行うにはどうすればよいかということです。

4

2 に答える 2

10

これは、私が投げたものをすべて拒否するように見えますが、リテラル文字列を受け入れます。

#define my_assert(test, message)\
    static_assert(\
        (\
             std::is_convertible      <decltype(message), const char *>::value &&\
            !std::is_rvalue_reference <decltype(message)>::value &&\
            !std::is_pointer          <decltype(message)>::value &&\
            !std::is_array            <decltype(message)>::value &&\
            !std::is_class            <decltype(message)>::value\
        ),\
        "string literal required"\
    );\
    assert((message, (test)))

これが実際に完全に正しいかどうか、および/またはこの検出を行うためのより簡単な方法があるかどうかを知りたいと思います。

于 2013-02-11T02:36:40.120 に答える