Home Dashboard Directory Help
Search

Variadic template bug? by James K Edwards


Status: 

Closed
 as Deferred Help for as Deferred


1
0
Sign in
to vote
Type: Bug
ID: 773475
Opened: 12/4/2012 5:54:57 PM
Access Restriction: Public
0
Workaround(s)
view
0
User(s) can reproduce this bug

Description

I have a strange bug in the following code. Sorry for all the code, but I can't get a simplified case to happen.

#pragma once
#include <type_traits>
#include <string>
#include <exception>
#include <assert.h>
#include <cstdio>
#include <iostream>

template<class _Ty>
struct _is_char : std::false_type {};

template<>
struct _is_char<char>    : std::true_type {};

template <class _Ty>
struct _is_c_string : std::false_type {};

template<class _Ty>
struct _is_c_string<_Ty *> : _is_char<typename std::remove_cv<_Ty>::type> {};

template<class _Ty>
struct is_c_string : _is_c_string<typename std::remove_cv<_Ty>::type> {};

template <typename T>
typename std::enable_if<std::is_integral<T>::value, long>::type normalizeArg(T arg)
{std::cout << "LongType/n"; arg;}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, double>::type normalizeArg(T arg)
{std::cout << "FloatType/n";return arg;}

template <typename T>
typename std::enable_if<std::is_pointer<T>::value, T>::type normalizeArg(T arg)
{std::cout << "PointerType/n";return arg;}

const char* normalizeArg(const std::string& arg)
{std::cout << "StringType/n";return arg.c_str();}

void check_printf(const char* f)
{
    for (; *f; ++f)
    {
        if (*f != '%' || *++f == '%') continue;
        throw std::exception("Too many format specifiers");
    }
}

template <typename T, typename... Ts>
void check_printf(const char* f, const T& t, const Ts&... ts)
{
    for (; *f; ++f)
    {
        if (*f != '%' || *++f == '%') continue;

        switch (*f)
        {
        default: throw std::exception("Invalid format");
        case 'd':
            if(!std::is_integral<T>::value)
            {
                throw std::exception("T is not an integral");
            }
            break;
        case 'f': case 'g':
            if(!std::is_floating_point<T>::value)
            {
                throw std::exception("T is not a float");
            }
            break;
        case 's':
            if(!is_c_string<T>::value)
            {
                throw std::exception("T is not a c string");
            }
            break;
        }
        return check_printf(++f, ts...);
    }
    throw std::exception("Too few format specifiers");
}

template <typename... Ts>
int safe_printf(const char* f, const Ts&... ts)
{
    check_printf(f, normalizeArg(ts)...);
    return printf(f, normalizeArg(ts)...);
}

#include "SafePrintf.h"
#include <string>
#include <iostream>

template <typename T>
bool StringCheck(T v)
{
    return is_c_string<T>::value;
}

void main()
{
    std::string str("Try this out.");
    const int i = 5;
    float f = 0.123f;

    try
    {
        safe_printf("This is from safe printf. int %d, string %s, and a float %f", i, str, f);
    }
    catch(std::exception e)
    {
        std::cout << e.what();
    }
}


The problem is I get an exception that str is not a c style string even though it goes through normalizeArg(). Nothing from normalizeArg gets printed, but the type in the debugger shows std basic string and break points in the normalizeArg functions do not hit.
Details
Sign in to post a comment.
Posted by James K Edwards on 2/2/2013 at 11:36 AM
LOL!
Yeah, In all my futzing to get it to work it looks like I broke it. :)
Posted by Microsoft on 1/30/2013 at 4:48 PM
Hi James,

The bug has been fixed and will be included in the next release/update of Visual Studio. Again, of course, we thank you for your feedback.

By the way, you got a missing `return' on line 26.

Karl Niu
VC++ Team
Posted by Microsoft on 12/5/2012 at 1:23 AM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.

Posted by Microsoft on 12/4/2012 at 6:52 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
File Name Submitted By Submitted On File Size  
main.cpp 12/4/2012 415 bytes