Variadic template bug? - by James K Edwards

Status : 

  Deferred<br /><br />
		The product team has reviewed this issue and has deferred it for consideration at a later time.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.


1
0
Sign in
to vote
ID 773475 Comments
Status Closed Workarounds
Type Bug Repros 0
Opened 12/4/2012 5:54:57 PM
Access Restriction Public

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.
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)