Because I like a challenge, I made a tiny Canvas class, to be used like:
int main() {
    using Canvas = BasicCanvas<160, 80>;
    Canvas canvas;
    canvas.origin = {canvas.cols()/3, canvas.rows()/3};
    canvas.axes();
    canvas.plot([](double x) { return  x; });
    canvas.plot([](double  ) { return -8; });
    canvas.plot([](double x) { return 3*log(x); });
    canvas.plot([](double x) { return 4*sin(x/2); });
    canvas.plot([](double x) { return 24*cos(x/12); });
    std::cout << canvas;
}
Which prints 
Or commenting out the origin assignment: 
Implementation
The implementation basically iterates through the positions on the x axis and plots approximate line drawing characters depending on the angle (first derivative) of the function at that point:
template <size_t Columns = 100, size_t Rows = 50>
struct BasicCanvas {
    using Line   = std::array<char, Columns>;
    using Screen = std::array<Line, Rows>;
    struct Coord { size_t x, y; };
    static constexpr size_t rows() { return Rows; }
    static constexpr size_t cols() { return Columns; }
    Screen screen;
    Coord origin;
    BasicCanvas(Coord origin = {Columns/2, Rows/2}) : origin(origin) {
        Line empty;
        std::fill(empty.begin(), empty.end(), '.');
        std::fill(screen.begin(), screen.end(), empty);
    }
    friend std::ostream& operator<<(std::ostream& os, BasicCanvas const& c) {
        for (auto& line : c.screen) {
            os.write(line.data(), line.size()) << "\n";
        }
        return os;
    }
    Line&       operator[](size_t y)          { return screen.at(screen.size()-(y+1)); }
    Line const& operator[](size_t y) const    { return screen.at(screen.size()-(y+1)); }
    char&       operator[](Coord coord)       { return operator[](coord.y).at(coord.x); }
    char const& operator[](Coord coord) const { return operator[](coord.y).at(coord.x); }
    void axes() {
        for (auto& line : screen)
            line.at(origin.x) = '|';
        auto& y_axis = operator[](origin.y);
        for (auto& cell : y_axis)
            cell = '-';
        y_axis.at(origin.x) = '+';
    }
    template <typename F>
    void plot(F f, double scaleX = 1.0, double scaleY = 1.0) {
        for (size_t x_tick = 0; x_tick < Columns; ++x_tick) {
            auto x = (x_tick * scaleX) - origin.x;
            auto y = f(x);
            auto y_ = derivative(f, x, scaleX/2);
            size_t y_tick = (y / scaleY) + origin.y;
            if (y_tick < Rows)
                operator[]({x_tick, y_tick}) = glyph(y_);
        }
    }
  private:
    template <typename F>
    auto derivative(F const& f, double x, double dx = 0.01) {
        return (f(x+dx)-f(x-dx))/(2*dx);
    }
    char glyph(double tangent) {
        auto angle = atan(tangent);
        while (angle < 0) 
            angle += 2*M_PI;
        int angle_index = 2.0 * angle / atan(1);
        return R"(--/||\--)"[angle_index % 8];
    }
};
Full Listing
Live On Coliru
(simplified function selection):
#include <iostream>
#include <array>
#include <cmath>
template <size_t Columns = 100, size_t Rows = 50>
struct BasicCanvas {
    using Line   = std::array<char, Columns>;
    using Screen = std::array<Line, Rows>;
    struct Coord { size_t x, y; };
    static constexpr size_t rows() { return Rows; }
    static constexpr size_t cols() { return Columns; }
    Screen screen;
    Coord origin;
    BasicCanvas(Coord origin = {Columns/2, Rows/2}) : origin(origin) {
        Line empty;
        std::fill(empty.begin(), empty.end(), ' ');
        std::fill(screen.begin(), screen.end(), empty);
    }
    friend std::ostream& operator<<(std::ostream& os, BasicCanvas const& c) {
        for (auto& line : c.screen) {
            os.write(line.data(), line.size()) << "\n";
        }
        return os;
    }
    Line&       operator[](size_t y)          { return screen.at(screen.size()-(y+1)); }
    Line const& operator[](size_t y) const    { return screen.at(screen.size()-(y+1)); }
    char&       operator[](Coord coord)       { return operator[](coord.y).at(coord.x); }
    char const& operator[](Coord coord) const { return operator[](coord.y).at(coord.x); }
    void axes() {
        for (auto& line : screen)
            line.at(origin.x) = '|';
        auto& y_axis = operator[](origin.y);
        for (auto& cell : y_axis)
            cell = '-';
        y_axis.at(origin.x) = '+';
    }
    template <typename F>
    void plot(F f, double scaleX = 1.0, double scaleY = 1.0) {
        for (size_t x_tick = 0; x_tick < Columns; ++x_tick) {
            auto x = (x_tick * scaleX) - origin.x;
            auto y = f(x);
            auto y_ = derivative(f, x, scaleX/2);
            size_t y_tick = (y / scaleY) + origin.y;
            if (y_tick < Rows)
                operator[]({x_tick, y_tick}) = glyph(y_);
        }
    }
  private:
    template <typename F>
    auto derivative(F const& f, double x, double dx = 0.01) {
        return (f(x+dx)-f(x-dx))/(2*dx);
    }
    char glyph(double tangent) {
        auto angle = atan(tangent);
        while (angle < 0) 
            angle += 2*M_PI;
        int angle_index = 2.0 * angle / atan(1);
        return R"(--/||\--)"[angle_index % 8];
    }
};
int main() {
    using Canvas = BasicCanvas<60, 30>;
    Canvas canvas;
    //canvas.origin = {canvas.cols()/3, canvas.rows()/3};
    canvas.axes();
    canvas.plot([](double x) { return  x; });
    //canvas.plot([](double  ) { return -8; });
    canvas.plot([](double x) { return 3*log(x); });
    canvas.plot([](double x) { return 4*sin(x/2); });
    //canvas.plot([](double x) { return 24*cos(x/12); });
    std::cout << canvas;
}
Prints
                              |             /               
                              |            /                
                              |           /                 
                              |          /                  
                              |         /                  -
                              |        /           -------- 
                              |       /      ------         
                              |      /   ----               
                              |     / ---                   
                              |    /--                      
                              |   --                        
       ---          --\       | /--          --\         /--
      /   \        /          | /  \        /               
                  /    \      |/                \       /   
-----/-----\------------------/|----\------/----------------
                 /      \    /|                  \     /    
    /       \               //|      \    /                 
\               /        \ /  |          /        \   /     
 --/         \--          --/ |       \--          ---      
                         /    |                             
                        /     |                             
                       /      |                             
                      /       |                             
                     /        |                             
                    /         |                             
                   /          |                             
                  /           |                             
                 /            |                             
                /             |                             
               /              |