C++ Templates

【C++ Templates(26)】调试模板

2018-07-12  本文已影响63人  downdemo

浅实例化(Shallow Instantiation)

template<typename T>
void clear (T& p)
{
    *p = 0; // assumes T is a pointer-like type
}

template<typename T>
void core (T& p)
{
    clear(p);
}

template<typename T>
void middle (typename T::Index p)
{
    core(p);
}

template<typename T>
void shell (T const& env)
{
    typename T::Index i;
    middle<T>(i);
}
class Client
{
public:
    using Index = int;
};

int main()
{
    Client mainClient;
    shell(mainClient);
}
void ignore(T const&)
{
}

template<typename T>
void shell (T const& env)
{
    class ShallowChecks
    {
        void deref(typename T::Index ptr) {
            ignore(*ptr);
        }
    };
    typename T::Index i;
    middle(i);
}

Concept Checking

静态断言(Static Assertion)

static_assert(sizeof(void*) * CHAR_BIT == 64, "Not a 64-bit platform");
// debugging/hasderef.hpp

#include <utility> // for declval()
#include <type_traits> // for true_type and false_type

template<typename T>
class HasDereference {
private:
    template<typename U> struct Identity;
    template<typename U> static std::true_type
        test(Identity<decltype(*std::declval<U>())>*);
    template<typename U> static std::false_type
        test(...);
public:
    static constexpr bool value = decltype(test<T> (nullptr))::value;
};
void shell (T const& env)
{
    static_assert(HasDereference<T>::value, "T is not dereferenceable");
    typename T::Index i;
    middle(i);
}
template<typename T>
class C {
    static_assert(HasDereference<T>::value,
        "T is not dereferenceable");
    static_assert(std::is_default_constructible<T>::value,
        "T is not default constructible");
    ...
};

原型(Archetype)

// T must be EqualityComparable, meaning:
// two objects of type T can be compared with ==
// and the result converted to bool
template<typename T>
int find(T const* array, int n, T const& value);
template<typename T>
int find(T const* array, int n, T const& value) {
    int i = 0;
    while(i != n && array[i] != value)
        ++i;
    return i;
}
class EqualityComparableArchetype
{
};

class ConvertibleToBoolArchetype
{
public:
    operator bool() const;
};

ConvertibleToBoolArchetype
operator==(EqualityComparableArchetype const&,
    EqualityComparableArchetype const&);
template int find(EqualityComparableArchetype const*, int,
    EqualityComparableArchetype const&);
template<typename T>
int find(T const* array, int n, T const& value) {
    int i = 0;
    while(i != n && !(array[i] == value))
        ++i;
    return i;
}
class ConvertibleToBoolArchetype
{
public:
    operator bool() const;
    bool operator!() = delete; // logical negation was not explicitly required
};

跟踪程序(Tracer)

// debugging/tracer.hpp

#include <iostream>
class SortTracer {
private:
    int value; // integer value to be sorted
    int generation; // generation of this tracer
    inline static long n_created = 0; // number of constructor calls
    inline static long n_destroyed = 0; // number of destructor calls
    inline static long n_assigned = 0; // number of assignments
    inline static long n_compared = 0; // number of comparisons
    inline static long n_max_live = 0; // maximum of existing objects

    // recompute maximum of existing objects
    static void update_max_live() {
        if (n_created-n_destroyed > n_max_live) {
            n_max_live = n_created-n_destroyed;
        }
    }

public:
    static long creations() {
        return n_created;
    }
    static long destructions() {
        return n_destroyed;
    }
    static long assignments() {
        return n_assigned;
    }
    static long comparisons() {
        return n_compared;
    }
    static long max_live() {
        return n_max_live;
    }

public:
    // constructor
    SortTracer (int v = 0) : value(v), generation(1) {
        ++n_created;
        update_max_live();
        std::cerr << "SortTracer #" << n_created
            << ", created generation " << generation
            << " (total: " << n_created - n_destroyed
            << ")\n";
    }

    // copy constructor
    SortTracer (SortTracer const& b)
    : value(b.value), generation(b.generation+1) {
        ++n_created;
        update_max_live();
        std::cerr << "SortTracer #" << n_created
            << ", copied as generation " << generation
            << " (total: " << n_created - n_destroyed
            << ")\n";
    }

    // destructor
    ~SortTracer() {
        ++n_destroyed;
        update_max_live();
        std::cerr << "SortTracer generation " << generation
            << " destroyed (total: "
            << n_created - n_destroyed << ")\n";
    }

    // assignment
    SortTracer& operator= (SortTracer const& b) {
        ++n_assigned;
        std::cerr << "SortTracer assignment #" << n_assigned
            << " (generation " << generation
            << " = " << b.generation
            << ")\n";
        value = b.value;
        return *this;
    }

    // comparison
    friend bool operator < (SortTracer const& a, SortTracer const& b) {
        ++n_compared;
        std::cerr << "SortTracer comparison #" << n_compared
            << " (generation " << a.generation
            << " < " << b.generation
            << ")\n";
        return a.value < b.value;
    }

    int val() const {
        return value;
    }
};
// debugging/tracertest.cpp
#include <iostream>
#include <algorithm>
#include "tracer.hpp"

int main()
{
    // prepare sample input:
    SortTracer input[] = { 7, 3, 5, 6, 4, 2, 0, 1, 9, 8 };

    // print initial values:
    for (int i=0; i<10; ++i) {
        std::cerr << input[i].val() << ' ';
    }
    std::cerr << '\n';

    // remember initial conditions:
    long created_at_start = SortTracer::creations();
    long max_live_at_start = SortTracer::max_live();
    long assigned_at_start = SortTracer::assignments();
    long compared_at_start = SortTracer::comparisons();

    // execute algorithm:
    std::cerr << "---[ Start std::sort() ]--------------------\n";
    std::sort<>(&input[0], &input[9]+1);
    std::cerr << "---[ End std::sort() ]----------------------\n";

    // verify result:
    for (int i=0; i<10; ++i) {
        std::cerr << input[i].val() << ' ';
    }
    std::cerr << "\n\n";

    // final report:
    std::cerr << "std::sort() of 10 SortTracer's"
        << " was performed by:\n "
        << SortTracer::creations() - created_at_start
        << " temporary tracers\n "
        << "up to "
        << SortTracer::max_live()
        << " tracers at the same time ("
        << max_live_at_start << " before)\n "
        << SortTracer::assignments() - assigned_at_start
        << " assignments\n "
        << SortTracer::comparisons() - compared_at_start
        << " comparisons\n\n";
}
std::sort() of 10 SortTracer's was performed by:
9 temporary tracers
up to 11 tracers at the same time (10 before)
33 assignments
27 comparisons

Oracles

上一篇 下一篇

猜你喜欢

热点阅读