How do I define a custom literal suffix for a typeset?

Jun 19, 2013 at 6:20am
Suppose I have typedef'd a double, and now want to have a literal of this type. How can I achieve this?

1
2
typedef double signalf;
signalf operator""(double val) {return (signalf) val;} // error  


I would have thought this would be simple, but for some reason that won't compile on visual studio 2012. I'm not so much interested in discussing my reasons for doing this (I think the benefits are self evident) but would like to know why this isn't compiling... Thanks.
Jun 19, 2013 at 6:56am
1. A literal operator must specify a literal suffix identifier.

2. For a non-raw literal operator for floating point types, the parameter must be a long double.

3. A raw literal operator must either have a single const char* parameter
or it must be a variadic template of elements of type char

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
template< char FIRST, char... REST > struct binary
{
    static_assert( FIRST == '0' || FIRST == '1', "invalid binary digit" ) ;
    enum { value = ( ( FIRST - '0' ) << sizeof...(REST) ) + binary<REST...>::value  } ;
};
 
template<> struct binary<'0'> { enum { value = 0 } ; };
template<> struct binary<'1'> { enum { value = 1 } ; };


// raw literal operator 
template<  char... LITERAL > inline
constexpr unsigned int operator "" _b() { return binary<LITERAL...>::value ; }
 
// raw literal operator 
template<  char... LITERAL > inline
constexpr unsigned int operator "" _B() { return binary<LITERAL...>::value ; }
 
// non-raw literal operator 
typedef double signalf;
constexpr signalf operator"" _percent( long double val) { return val / 100 ; }
 
#include <iostream>
 
int main()
{
    std::cout  << 12.34_percent << '\n' // prints 0.1234
               << 10101_B << ", " << 011011000111_b  << '\n' ; // prints 21, 1735
}

http://ideone.com/cTdkex
Jun 19, 2013 at 7:03am
Oh of course, so this should work then:

signalf operator"" sf_ (double val) {return (signalf) val;} // error

Sadly this still doesn't compile but I just figured out it's because MS C++ doesn't support user defined literals... back to plain old casting for me then...
Jun 19, 2013 at 7:10am
signalf operator"" sf_ ( /*double*/ long double val) {return (signalf) val;} // *** long double

However, if MS C++ doesn't support user defined literals...
Jun 19, 2013 at 8:55am
Is there any way to emulate this behaviour using macros? So that I can still get this behaviour;

1
2
3
4
5
6
7
8
9
 
typedef double signalf;
typedef float physf;

//Some macro here that replaces any instance of "_sf" with nothing and every instance of "_pf" with "f" 

signalf val1 = 1.234_sf; // this literal is "1.234" to the compiler and therefore double 
physf val2 = 1.234_pf; // this literal is "1.234f" to the compiler and therefore float


This would be a nice intermediate solution because I could just swap the macro over for the literal overload and wouldn't have to wade through my entire program once Microsoft does implement user defined literals...
Jun 19, 2013 at 9:20am
Why don't you just do this?

1
2
3
4
5
6
7
8
9
10
11
12
typedef double signalf;
typedef float physf;

inline signalf sf( double d ) { return d ; }

inline physf pf( double d ) { return d ; }

int main()
{
    auto val1 = sf(1.234) ;
    auto val2 = pf(1.234) ;
}
Jun 19, 2013 at 5:59pm
That could work. Thanks :)
Topic archived. No new replies allowed.