5

コードの問題を調査しようとするとき、私はデバッグ印刷のファンです。

cout << "foo:" << foo << "bar:" << bar << "baz:" << baz;

私はこのようなコードを頻繁に書くので、汎用的で入力しやすいコードにできれば最高です。多分このようなもの:

DEBUG_MACRO(foo, bar, baz);

foobarおよびbazは文字列ではなく変数名に解決されますが、それらの変数名を使用して文字列"foo:""bar:"、およびを作成することは可能"baz:"ですか? 不特定の数のパラメータを取る関数またはマクロを作成できますか?

4

3 に答える 3

4

C++ 11 を使用している場合は、可変個引数テンプレートを使用して型安全でかなりきちんとしたことを行うことができます。たとえば、次のようになります。

#include <string>
#include <iostream>

template <typename T>
void debug(const T& v) {
  std::cout << v << "\n";
}

template <typename T, typename... Tail>
void debug(const T& v, const Tail& ...args) {
  std::cout << v << " ";
  debug(args...);
}

#define NVP(x) #x":", (x)

int main() {
  int foo=0;
  double bar=0.1;
  std::string f="str";
  debug(NVP(foo),NVP(bar),NVP(f));
}

ここでの NVP マクロは完全にオプションであり、コードで参照した名前を出力したい場合にのみ必要です。

NVP ビットを本当にスキップしたい場合は、Boost プリプロセッサ ライブラリを使用できます (または独自にロールします)。

#include <string>
#include <iostream>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>

template <typename T>
void debug_impl(const T& v) {
  std::cout << v << "\n";
}

template <typename T, typename... Tail>
void debug_impl(const T& v, const Tail& ...args) {
  std::cout << v << " ";
  debug_impl(args...);
}

#define NVP(x) #x":", (x)
#define MEMBER( r, data, i, elem ) BOOST_PP_COMMA_IF( i ) NVP(elem)

#define debug( members )                                \
  debug_impl(                                           \
  BOOST_PP_SEQ_FOR_EACH_I( MEMBER,, members )           \
  )


int main() {
  int foo=0;
  double bar=0.1;
  std::string f="str";
  debug((foo)(bar)(f));
}

少し奇妙な構文の代償として。私の例は、この回答に基づいています。これを「純粋な」C++11 ソリューションとして直接解決するために、可変引数マクロを使用しようとしましたが、リストを再帰することは、期待するよりも難しいことがわかりました。

于 2012-06-05T15:22:57.650 に答える
1
#define DEBUG_MACRO(name) std::cout << #name << " = " << name << std::endl;

Example: http://ideone.com/agw4i

于 2012-06-05T15:13:13.737 に答える
0

不特定の数のパラメーターを取る関数を作成できますか?

はい、しかし通常はそうすべきではありません。

宣言で省略記号を使用すると、指定されていない数のパラメーターを取る関数を宣言できます。

int foo(string foo, ...)

しかし、これには大きな問題があります。最大の問題は、型の安全性が損なわれることです。パラメータ リストが指定されていない別の関数を間違って使用するとどうなるかを考えてみましょう。

int n = 42;
char buf[256] = {};
sprintf(buf, "%s", n);

これはバグです。文字列を指定しましたが、int. 最良のシナリオは、プログラムを初めてデバッグするときにこれが実行され、すぐに爆発することです。ただし、本番環境で初めて例外的な状況が発生するまでコードが実行されず、取引日の途中でプログラム全体が停止する可能性が非常に高くなります。クライアントはあなたに電話して怒鳴ったり、ユニットをキャンセルしたりします... OK、私は大げさなことを言っていますが、重要なのは、愛憎関係にある場合でも、型の安全性はあなたの友人です。

于 2012-06-05T15:17:33.260 に答える