Is there a workaround for this C4702 link-time warning?
I'm using boost::variant and am having trouble compiling in release mode. I am working in VC2010 with warning level 4 and warnings as errors. The code below compiles fine in debug mode, but in release mode I get a bunch of "Unreachable code" C4702 warnings emitted at link time (presumably I'm getting compiler warnings here because there is link time code generation when optimisations are enabled.)
Has anybody successfully disabled these warnings in this situation? I would prefer to keep the high warning level and warnings as errors if possible.
#pragma warning( disable:4702 )
... doesn't seem to work here. Here is some sample code:
#include <boost/variant.hpp>
struct null{};
typedef boost::variant< null, double > variant_t;
class addition_visitor
: public boost::static_visitor< variant_t >
{
public:
template< typename T, typename U >
variant_t operator()( const T&, const U& ) const
{
throw( "Bad types" );
开发者_C百科}
variant_t operator()( const double& left, const double& right ) const
{
return variant_t( left * right );
}
};
int main(int /*argc*/, char** /*argv*/)
{
variant_t a( 3.0 ), b( 2.0 );
variant_t c = boost::apply_visitor( addition_visitor(), a, b );
return 0;
}
The warning is triggered by the templated operator(), which I'm using to catch attempts to apply the visitor to bad variant types.
After a spot of lunch and a stroll, I've got an unsatisfying but functioning work-around. Instead of returning a variant from my visitor and throwing on error, I return a success boolean and store a result, thus:
#include <boost/variant.hpp>
struct null{};
typedef boost::variant< null, double > variant_t;
class addition_visitor
: public boost::static_visitor< bool >
{
public:
template< typename T, typename U >
bool operator()( const T&, const U& )
{
//throw( "Bad types" );
return false;
}
bool operator()( const double& left, const double& right )
{
result = variant_t( left * right );
return true;
}
variant_t result;
};
int main(int /*argc*/, char** /*argv*/)
{
variant_t a( 3.0 ), b( 2.0 );
addition_visitor v;
if( !boost::apply_visitor( v, a, b ) )
{
throw( "Bad types" );
}
variant_t c = v.result;
return 0;
}
Why provide a body for the template operator at all?
I haven't got Boost handy here so I can't check for you, but the fact that the templated operator has a body most probably means that any and all calls, regardless of type, will compile fine, then throw an error at runtime.
Leave the body of the template operator out, and it will simply refuse to link when used with any other type than double.
The #pragma doesn't work because this is a link time not a compile time warning.
You could suppress the warning in release mode. I believe /ignore:xxxx on the linker command line will do the trick.
I had a very similar problem in a Visual Studio 2012 MFC project; the same warning came from the <memory> header file, also during Release link time code generation.
I solved it by adding #pragma warning(disable:4702) early in the pre-compiled header file ("stdafx.h" in my case, just before #including STL header files).
If I declare the non-double method but don't provide an implementation then I get an "unresolved external" linker error.
Try to add inline
specifier at the template operator definition. Then MSVC shouldn't need its body compiling the class itself. So instead of unresolved external
you'll be getting compile-time errors only when your code tries to use this template. As I understand - this is exactly what you want.
Make the templated operator()(...)
private and don't provide an implementation. That will catch the use of it at compile time instead of link time.
精彩评论