Sign in to follow this  
SiS-Shadowman

Compiler error C2275

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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;
}




Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this