Search code examples
c++templatesc++11stlstdstring

default const char* template argument in a template template function


I am playing around with a generic template template function to output containers to the console.

To do this, I wish to provide a defaulted separator. It works defaulting a template argument to const char (but then I need to do a silly string construction) or defaulting the const char * function argument (I know this is a perfectly good solution and might be the preferred).

What I want to find out is if there is a way to default the template argument to a specific const char* value? Because the template arguments are meant to declare types not derivatives like (*, &, etc. - yet const works?) I am not sure it is possible but a defaulted template argument and more efficient than the first implementation underneath is what I am looking for.

#include <cstdlib>
#include <iostream>
#include <thread>
#include <iomanip>
#include <algorithm>
#include <vector>
#include <iterator>

using namespace std;

// This Works
template <template <typename , typename > class Container, class Element, class Allocator, const char sep= ','>
void displayContents(const Container<Element, Allocator>& inputContainer)
{
    string seperator(1, sep); 
    copy(inputContainer.cbegin(), inputContainer.cend(), ostream_iterator<Element>(cout, seperator.c_str())); // not all that efficient...
    cout << endl;
};

// This works fine
template <template <typename, typename > class Container, class Element, class Allocator>
void displayContentsWithDefaultArgs(const Container<Element, Allocator>& inputContainer, const char* sep = ",")
{
    copy(inputContainer.cbegin(), inputContainer.cend(), ostream_iterator<Element>(cout, sep));
    cout << endl;
};

// how can we get this to work (more effectively than displayContents above?)
template <template <typename, typename > class Container, class Element, class Allocator, const char* sep = ",">
void displayContentsWithDefaultTemplateArgs(const Container<Element, Allocator>& inputContainer)
{
    copy(inputContainer.cbegin(), inputContainer.cend(), ostream_iterator<Element>(cout, sep));
    cout << endl;
};

int main(int argc, char** argv) {

    vector<int> v = { 1 ,2 ,3, 4 };
    vector<int> v1;
    copy(v.cbegin(), v.cend(), back_inserter(v1));
    displayContents(v1);
    displayContentsWithDefaultArgs(v1);
    displayContentsWithDefaultTemplateArgs(v1);
    return 0;
}

Solution

  • It seems to me you want to combine two separate things in one: default type and default variable value of that type. But that's impossible and it seems pretty reasonable to me.
    Slightly flexible approach will do what you asked for:

    template <template <typename, typename > class Container, class Element, class Allocator, class Sep = const char*>
    void displayContentsWithDefaultTemplateArgs(const Container<Element, Allocator>& inputContainer, Sep sep = ",")
    {
        copy(inputContainer.cbegin(), inputContainer.cend(), ostream_iterator<Element>(cout, sep));
        cout << endl;
    };