Function template specialization for literal strings

I have a class I am working on which let's me use the << operator on various types. I have defined the operator for integral types and for strings. I would like the definition for strings to only apply to literal strings and not pointers to strings. For example:

LOGSTREAM() << "Oh my!!"; // OK

std::string foo;
LOGSTREAM() << foo.c_str(); // NOPE

But I can't seem to find a way to code this.

Thanks!!!
-Jim.

class LOGSTREAM {
. . .

enum class enabler_t { };
template<typename T>
using EnableIf = typename std::enable_if<T::value, enabler_t>::type;

template<class T, EnableIf<std::is_integral<T>>...>
LOGSTREAM& operator <<(T arg) {
. . .
return *this;
}
template <class T, EnableIf<std::is_same<const char*, T>>...>
LOGSTREAM& operator <<(T arg) {
. . .
return *this;
}

. . .

};
> "Oh my!!"
that's a const char *

> foo.c_str()
that's also a const char *

there is no «literal» modifier, you can't distinguish them.
¿why do you want to make your interface so awful?
Overload, don't specialise: http://www.gotw.ca/publications/mill17.htm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <type_traits>

struct logstm
{
    logstm( std::ostream& stm ) : stm(stm) {}

    template < typename T >
    typename std::enable_if< std::is_integral<T>::value, logstm& >::type // ovrload for integral types
    operator << ( const T& v ) { stm << v << ' ' ; return *this ; }

    template < std::size_t N > // overload for literal strings (narrow)  
    logstm& operator << ( const char (&literal_string)[N] ) { stm << '"' << literal_string << "\" " ; return *this ; }

    std::ostream& stm ;
};

int main()
{
     logstm lg(std::cout) ;
     lg << 1234 << "hello world!" << '\n' ;
}

http://coliru.stacked-crooked.com/a/b5c88ffe2e30eae6

The overload for literal strings is really one for 'array of const char'
Last edited on
Yes!!!
Ok, followup:

Let's say in addition to supporting literal strings I also want to support non-literal string in a separate operator<< definition.

Edit:

Nevermind I think have it with:

// overload for integral types
template < typename T >
typename std::enable_if< std::is_integral<T>::value, LOGSTREAM& >::type
operator << ( const T& arg ) {
elems_.push_back(arg);
return *this;
}
// overload for literal strings (narrow)
template < std::size_t N >
LOGSTREAM& operator << ( const char (&arg)[N] ) {
elems_.push_back(arg);
return *this;
}
// for non-literal strings
template < typename T >
typename std::enable_if< std::is_same<const char*, T>::value, LOGSTREAM& >::type
operator << ( T arg ) {
elems_.push_back(LOGELEM(LOGTYPE::STR, arg));
return *this;
}
Last edited on
Overload; as many times as you want. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
struct logstm
{
    logstm( std::ostream& stm ) : stm(stm) {}

    template < typename T >
    typename std::enable_if< std::is_integral_v<T>, logstm& >::type // integral types
    operator << ( const T& v ) { stm << v << ' ' ; return *this ; }

    template < std::size_t N > // literal strings (narrow) ie. array of const char
    logstm& operator << ( const char (&literal_string)[N] ) { stm << '"' << literal_string << "\" " ; return *this ; }
    
    // more overloads
    logstm& operator << ( const char* cstr ) ;
    logstm& operator << ( const std::string& str ) ;
    logstm& operator << ( std::string_view str_view ) ;

    std::ostream& stm ;
};




Topic archived. No new replies allowed.