简体   繁体   English

C ++元编程

[英]C++ Meta-programming

During development of my project in C++ I have a frequent need of debugging and I usually use this macro to do it 在用C++开发我的项目期间,我经常需要调试,我通常使用这个宏来完成它

#define DBUG(a) {std::cout << #a << " : " << a << std::endl;};

But many times I need to do something like this 但很多时候我需要做这样的事情

int a;
std :: string b;
double c;
...
...
DBG(a); DBG(b); DBG(c);

But ideally it might be possible to just write DBUG(a, b, c) or DBG(a, b, c, d, e) for more variables to achieve something like this. 但理想情况下,可以只编写DBUG(a, b, c)DBG(a, b, c, d, e)以获得更多变量来实现这样的功能。 After some research this looked like a problem in meta-programming or more specifically code-generation, but because of my limited knowledge in these areas I could not find a way to go about it. 经过一些研究,这看起来像是元编程中的一个问题,或者更具体地说是代码生成,但由于我在这些领域的知识有限,我无法找到解决方法。

If possible I would like to solve this without using Boost or other external libraries, and using the features in C++98 although if it is not possible I'm willing to use C++11 . 如果可能的话,我想在不使用Boost或其他外部库的情况下解决这个问题,并使用C++98的功能,尽管如果不可能,我愿意使用C++11

I don't like a limitation to a specific number of arguments. 我不喜欢限制特定数量的参数。 I didn't find a nice approach which decodes the name statically so the names are put together as a comma separated string and then decoded at run-time. 我没有找到一个静态解码名称的好方法,因此名称以逗号分隔的字符串组合在一起,然后在运行时解码。 Overall, that may be a bit too heavy-weight but, at least, it does as was asked and has not limitation on the number of arguments (other than compiler limitations, that is): 总的来说,这可能有点过于沉重,但至少,它确实如所要求的那样,并且对参数的数量没有限制(除了编译器限制之外):

#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <tuple>
#include <vector>
#include <type_traits>
#include <stdlib.h>

template <int I, int S, typename... V>
typename std::enable_if<I == S>::type
debug_var(std::vector<std::string> const&, std::tuple<V...> const&)
{
}

template <int I, int S, typename... V>
typename std::enable_if<I != S>::type
debug_var(std::vector<std::string> const& n, std::tuple<V...> const& v)
{
    std::cout << n[I] << '=' << std::get<I>(v) << ' ';
    debug_var<I + 1, S>(n, v);
}

template <typename... V>
void debug(std::vector<std::string> const& n, std::tuple<V...> const& v)
{
    debug_var<0, sizeof...(V)>(n, v);
    std::cout << '\n' << std::flush;
}

std::vector<std::string> debug_names(char const* names)
{
    std::vector<std::string> result;
    std::istringstream in(names);
    for (std::string name; std::getline(in >> std::ws, name, ','); ) {
        result.push_back(name);
    }
    return result;
}

#define DEBUG(...) debug(debug_names(#__VA_ARGS__), std::tie(__VA_ARGS__));

int main()
{
    int a=1, b=2;
    DEBUG(a, b);
    DEBUG();
}

The code uses several features which were introduced by the 2011 revision of C++. 该代码使用了2011版C ++引入的几个功能。

Here's one solution adapted from this answer . 这是一个改编自这个答案的解决方案。 You have to define your macros to support up to a maximum number of parameters by changing the CHOOSER and DBG macros, as well as adding appropriate DBG# macros. 您必须通过更改CHOOSERDBG宏来定义宏以支持最多数量的参数,以及添加适当的DBG#宏。 It does require C++11, too. 它确实需要C ++ 11。

#include <iostream>

#define DBG1(a) std::cout << #a ": " << a << "\n"
#define DBG2(a, b) DBG1(a); DBG1(b)
#define DBG3(a, b, c) DBG2(a, b); DBG1(c)

#define CHOOSER(a, b, c, CHOICE, ...) CHOICE
#define DBG(...) CHOOSER(__VA_ARGS__, DBG3, DBG2, DBG1)(__VA_ARGS__)

int main() {
    int a{}, b{1}, c{5};
    DBG(a, b, c);
}

Output: 输出:

a: 0 a:0
b: 1 b:1
c: 5 c:5

您可以通过以下方式使用自己的DBUG(a)

DBUG(a << " " << b << " " << c);

How about using some good ol' C++11 variadic templates? 如何使用一些好的'C ++ 11可变参数模板?

#include <iostream>
#include <sstream>
#include <string>


template <typename T>
std::string make_string(const T& t)
{
    std::ostringstream oss;
    oss << t;
    return oss.str();
}

template <typename Thead, typename ... Ttail>
std::string make_string(const Thead& head, const Ttail& ... tail)
{
    return make_string(head) + make_string(tail...);
}

void debug(const std::string& msg)
{
    std::cout << "DEBUG: " << msg << std::endl;
}

void debug(void)
{
    std::cout << "DEBUG!" << std::endl;
}

template <typename ... Targs>
void debug(const Targs& ... args)
{
    debug(make_string(args...));
}



int main(void)
{
    int z;
    debug("We're gonna crash: ", &z, "!");
    debug();
    debug(3.14);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM