Compiler error C2275

Started by
5 comments, last by cache_hit 14 years, 3 months ago
What the... Simple problem:

class bad_cast : public exception
{
    template <typename source_type, typename expected_type>
    bad_cast() : exception( boost::format("%1% bla %2%") % typeid(source_type).name() % typeid(expected_type)) {}
};

template <typename value_type>
void some_function
{
    throw bad_cast<boost::any,value_type>();
}


Can anybody please tell me why (using Visual Studio 2008) I'm getting a C2275: bad_cast: illegal use of this type as an expression. Somehow I'm unable to see the error. *edit* I forgot to mention, the error of course only appears when actually calling some_function like this: some_function< math::vector<double> >() [Edited by - SiS-Shadowman on December 23, 2009 8:05:56 AM]
Advertisement
Is this actual code and what is the full error message?
I suspect that not using ".name()" on the second type is a typo and also no public constructor. In addition is this namespaced to stop conflicts with std::exception and std::bad_cast?

Please post actual or minimal code which show the error and the full error message.
"You insulted me!" I did not say that in the private message Tom Sloper!
I have that code on my laptop (which has no lan-connection currently), but I'll be posting the actual code & message when I'm home. You were right, the forgotten .name() is a typo and I also didn't include the namespace directive (the exception class is not inside the global namespace).

I'm currently working with a static function (exactly the same signature as the constructor I've posted here) which is properly compiling.
I totally forgot about the problem because of the ugly workaround I created.
I've just created a test-case that causes the mentioned compiler error. The code for bad_cast can be found in exception.hpp (see below). The really strange thing is that calling boostext::bad_cast::format<boost::any,T>() does NOT show this error and compiles just fine.

#include <boostext/exception.hpp>#include <boost/any.hpp>template <typename T>void some_function(){	throw boostext::bad_cast<boost::any,T>();	// Uncommenting the following line, and commenting the line above	// will make this code compile	// throw boostext::bad_cast::format<boost::any,T>();}int main(int argc, char* argv[]){	some_function<int>();}


Contents of boostext/exception.hpp:
#pragma once#include <boost/exception/all.hpp>#include "format.hpp"namespace boostext{	class exception : public std::exception, public boost::exception	{	public:		typedef boost::error_info<struct tag_file,std::string>     _file;		typedef boost::error_info<struct tag_function,std::string> _function;		typedef boost::error_info<struct tag_line,std::size_t>     _line;	public:		exception(const std::string& what)			: std::exception(what.c_str())		{}		const char* file() const		{			if( const std::string* err = boost::get_error_info<_file>( *this ) )				return err->c_str();			else				return "unknown";		}		const char* function() const		{			if( const std::string* err = boost::get_error_info<_function>( *this ) )				return err->c_str();			else				return "unknown";		}		std::size_t line() const		{			if( const std::size_t* err = boost::get_error_info<_line>( *this ) )				return *err;			else				return 0;		}	};	class bad_cast : public exception	{	public:		bad_cast(const std::string& what) : exception(what) {}		template <typename source_type, typename expected_type>		bad_cast()			: exception(boostext::format("bad cast from '%1%' to '%2%'")				% typeid(source_type).name()				% typeid(expected_type).name())		{}		template <typename source_type, typename expected_type>		bad_cast(const std::string& what)			: exception(boostext::format("%1%: bad cast from'%2%' to '%3%'")				% what				% typeid(source_type).name()				% typeid(expected_type).name())		{}		template <typename source_type, typename expected_type>		static bad_cast format()		{			return bad_cast(boostext::format("bad cast from '%1%' to '%2%'") % typeid(source_type).name() % typeid(expected_type).name());		}		template <typename source_type, typename expected_type>		static bad_cast format(const std::string& what)		{			return bad_cast(boostext::format("%1%: bad cast from '%2%' to '%3%'") % what % typeid(source_type).name() % typeid(expected_type).name());		}	};}


Contents of format.hpp:
namespace boostext{	template	<		class _char,		template <class> class _Traits = std::char_traits,		template <class> class _Ax = std::allocator	>	class basic_format : public boost::basic_format<_char, _Traits<_char>, _Ax<_char> >	{	public:		/// Typedef for the parent class		typedef boost::basic_format<_char, _Traits<_char>, _Ax<_char> >   BF;		/// Typedef for the underlying std::basic_string		typedef std::basic_string<_char, _Traits<_char>, _Ax<_char> >     _String;		/// Typedef for a type, describing sizes		typedef typename _String::size_type                               size_type;	public:		basic_format( const _String &fmt ) : boost::basic_format<_char,_Traits<_char>, _Ax<_char> >( fmt ) {}		template		<			class _Ty		>		basic_format<_char,_Traits, _Ax>& operator%(const _Ty& x)		{			// __super::operator%...			BF::operator%( x );			return *this;		}		operator _String() const		{			return str();		}	};	typedef basic_format<char>    format;	typedef basic_format<wchar_t> wformat;}
bad_cast is not a template class. You're writing

throw bad_cast<boost::any,value_type>();


the constructor is what's templatized, not the class.

I'd have to consult the standard, which I don't have handy, but I thought you cannot explicitly specify template arguments for a templated constructor, and the types can only be deduced at compile time by the compiler.
Ah, so that's the problem. So I'll either have to create a templated class that subclasses bad_cast(so I can catch any bad_cast) or stick with my function.
Thanks for explaining. It even does make sense, since those explicit template arguments could either belong to the class type or the constructor (if it were possible).
Quote:Original post by SiS-Shadowman
Ah, so that's the problem. So I'll either have to create a templated class that subclasses bad_cast(so I can catch any bad_cast) or stick with my function.
Thanks for explaining. It even does make sense, since those explicit template arguments could either belong to the class type or the constructor (if it were possible).


Yea. I'm sure there's some weird corner cases where the standard allows you to manually invoke a constructor, such as writing Foo::Foo(3,4,5), maybe involving placement new or something, but in general I think templated constructors are only possibly if there is at least 1 argument to the constructor of each parameterized type so that it can deduce them at compile time.

This topic is closed to new replies.

Advertisement