web-dev-qa-db-ja.com

static_assertを使用して、マクロに渡される型を確認します

残念ながら、かなりクレイジーなCを使用した元のバージョンのライブラリからいくつかのマクロが残っています。特に、特定のタイプがそれらに渡されることを期待する一連のマクロがあります。 次の線に沿って何かを行うことは可能ですか:

static_assert(decltype(retval) == bool);

そしてどのように?賢い選択肢はありますか?

はい、マクロが悪いことは承知しています。 C++はCではないことを知っています。

Update0

ここにいくつかの 関連コードソースファイル があります。提案は大歓迎です。元の質問は同じままです。

27
Matt Joiner

@ ncleBens の提案を使用して、これが最もクリーンであることがわかりました。

#include <type_traits>

static_assert(std::is_same<decltype(retval), bool>::value, "retval must be bool");
50
Matt Joiner

式があるのでdecltypeが必要なようですが、型を確認したいのです。これを行うには、すでに十分な方法があります(C++ 03)。たとえば、ブール値をチェックするには

inline void mustBeBool(bool) { }
template<typename T> inline void mustBeBool(T t) { & (&t); } // Takes address of rvalue (&t)

// Use:
#define DifficultMacro(B) do { mustBeBool(B); foo(B); } while (false)
3
MSalters

免責事項:これは悪い答えです。間違いなくはるかに優れた解決策があります。ほんの一例です:)

すでに実装されているはずですが、自分で実装するのは簡単です。

template <class T1, class T2> struct CheckSameType; //no definition
template <class T> struct CheckSameType<T,T>{}; //

template <class T1, class T2>
AssertHasType(T2)
{
   CheckSameType<T1, T2> tmp; //will result in error if T1 is not T2
}

このように使用するには:

AssertHasType<bool>(retval);

代替(GManが提案):

template <class T1, class T2> struct SameType
{
    enum{value = false};
}
template <class T> struct SameType<T,T>
{
    enum{value = true};
}; 

のように使用する

static_assert(SameType<decltype(retval), bool>::value);
2
Armen Tsirunyan

ほとんどのマクロは、inline関数やテンプレートに置き換えることができます。適切な例として、過度に巧妙な引数サイズチェックのPosix isnanマクロは、C++ 0xのテンプレートです。ああ、悪い例ですが、あなたはその考えを理解します。

そのルールの主な例外は、本質的に高水準の機能を実装するマクロです言語機能。たとえば、よりスマートな例外処理、共分散、またはパラメーター化された宣言のセット。

場合によっては、inline関数またはテンプレートとして合理的に表現できないマクロを、よりスマートな種類の前処理、つまりコード生成に置き換えることができます。次に、必要なコードを生成するスクリプトがどこかにあります。たとえば、マクロとテンプレートを使用して純粋なC++でオプションクラスを実行することは可能ですが、それは厄介であり、より簡単で保守しやすい代替手段として、必要なクラスを生成するスクリプトを使用できますが、追加料金がかかりますステップを構築し、複数の言語を処理します。

乾杯&hth。、

constおよびvolatile修飾子を気にし、タイプのconstおよびvolatileの部分も、現在のタイプと正確に一致するようにしたい場合と比較して、実行してください @ Matt Joinerが言うように

#include <type_traits>

static_assert(std::is_same<decltype(my_variable), uint64_t>::value, 
              "type must be `uint64_t`"); 

constは気にせず、constに関係なく、タイプが特定のタイプであることを確認したい場合は、代わりに次のようにします。ここではstd::remove_const<>::typeが必要であることに注意してください。

static_assert(std::is_same<std::remove_const<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t`");   

同じことがvolatileにも当てはまります。タイプのvolatile部分も気にしない場合は、std::remove_volatile<>::typeで無視できます。

static_assert(std::is_same<std::remove_volatile<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `volatile uint64_t`");

const OR volatileを気にしない場合は、std::remove_cv<>::typeで両方を削除できます。

static_assert(std::is_same<std::remove_cv<decltype(my_variable)>::type, uint64_t>::value, 
              "type must be `uint64_t` OR `const uint64_t` OR `volatile uint64_t` OR `volatile const uint64_t`");

参照:

  1. static_assertを使用して、マクロに渡される型を確認します
  2. https://en.cppreference.com/w/cpp/types/is_same
  3. https://en.cppreference.com/w/cpp/language/decltype
  4. https://en.cppreference.com/w/cpp/header/type_traits
  5. https://en.cppreference.com/w/cpp/types/remove_cv --std::remove_cv<>std::remove_const<>std::remove_volatile<>

関連:

  1. Cでの静的アサート [私自身の答え]
  2. Cで静的アサートを使用してマクロに渡されるパラメーターのタイプをチェックする方法 [私自身の質問]
  3. Cでのマクロ引数の型チェック
0
Gabriel Staples