How do I use a numeric_cast policy? - c++

So I have my own policy for uint64_t to uint32_t numeric cast
struct MyOverflowHandlerPolicy
{
void operator() ( boost::numeric::range_check_result ) {
std::cout << "MyOverflowHandlerPolicy called" << std::endl;
throw boost::numeric::positive_overflow();
};
} ;
How do I get it to be used by boost::numeric_cast?

In order to use numeric_cast, numeric_cast_traits specialization should defined on each type conversions. These specializations are already defined with default values for the built-in numeric types. It is possible to disable the generation of specializations for built-in types by defining BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS (details).
Here is a small running sample.
#include <iostream>
#include <stdexcept>
#define BOOST_NUMERIC_CONVERSION_RELAX_BUILT_IN_CAST_TRAITS
#include <boost/numeric/conversion/cast.hpp>
using namespace std;
struct YourOverflowHandlerPolicy
{
void operator() ( boost::numeric::range_check_result r ) {
cout << "YourOverflowHandlerPolicy called" << endl;
if (r != boost::numeric::cInRange) {
throw logic_error("Not in range!");
}
};
};
namespace boost { namespace numeric {
template <>
struct numeric_cast_traits<uint32_t, uint64_t>
{
typedef YourOverflowHandlerPolicy overflow_policy;
typedef UseInternalRangeChecker range_checking_policy;
typedef Trunc<uint64_t> rounding_policy;
};
template <>
struct numeric_cast_traits<uint64_t, uint32_t>
{
typedef YourOverflowHandlerPolicy overflow_policy;
typedef UseInternalRangeChecker range_checking_policy;
typedef Trunc<uint32_t> rounding_policy;
};
}} //namespace boost::numeric;
int main()
{
try {
cout << boost::numeric_cast<uint32_t>((uint64_t)1) << endl; // OK
cout << boost::numeric_cast<uint32_t>((uint64_t)1<<31) << endl; // OK
cout << boost::numeric_cast<uint32_t>((uint64_t)1<<32) << endl; // Exception
} catch (...) {
cout << "exception" << endl;
}
return 0;
}
Output:
YourOverflowHandlerPolicy called
1
YourOverflowHandlerPolicy called
2147483648
YourOverflowHandlerPolicy called
exception
Note: I have boost release 1.55.0, I don't know the minimum release level to get it compiled but it isn't compiled with 1.46.0. So, please check your boost release and update if necessary.

Related

Collect instantiated template types at compile time

Consider this snippet:
struct A {
template <typename T> void bar(const T &) {
/*
I would like to write something like:
if constexpr(type T already processed/T is already present in typelist)
...do something fancy
else if constexpr(type T not processed/T is not present in typelist)
*/
}
};
struct Msg1 {};
struct Msg2 {};
int main() {
A a;
a.bar(Msg1{});
a.bar(Msg1{});
}
Demo
Is it possible to see at compile time for which types the method bar was already instantiated?
Ideally, there would be some kind of growing typelist, where one can check at compile time for which types bar is already instantiated.
No. It is not possible to do so at compile time. However, it would be possible to do the following at runtime:
#include <typeindex>
#include <type_traits>
#include <unordered_set>
struct A {
private:
std::unordered_set<std::type_index> already_processed_ts;
public:
template<typename T>
void bar(const T&){
if(already_processed_ts.find(typeid(T)) != already_processed_ts.end())
std::cout << "Already processed " << typeid(T).name() << std::endl;
else{
already_processed_ts.insert(typeid(T));
std::cout << "Processing " << typeid(T).name() << "... \n";
}
}
}
struct Msg{};
int main()
{
f(Msg{}); // Prints "Processing 3Msg..." (at least on my compiler)
f(Msg{}); // Prints "Already processed 3Msg"
return 0;
}

Accessing struct and union member functions within a class

In this program I just want to test a structure and union within a class itself.
I had created a public struct, and declared a union within it.
I am using Visual Studio and Qt Creator to type this code.
I want to ask, is defining a struct within a class good and accessible?
I am having problem with that.
If this is correct, how could I access the method or data member of the struct from main?
I'd also like to use the union member of the struct.
If the method or functions of the struct are not accessible this way,. what's another way of doing it?
//************************************************************************************
#ifndef CTEST_H
#define CTEST_H
class CTest {
int value;
public:
CTest(int);
int getValue();
struct CTESTSTRUCT {
union CTESTUNION
{
enum CTestEnum {
var1 = 1
};
char varChar1 = 'Y';
char varChar2 /*= 'N'*/; //union atmost have one field initializer
};
int structValue();
int testVal;
};
~CTest();
};
#endif
//************************************************************************************
#include <iostream>
#include "CTest.h"
CTest::CTest(int argVal) : value(argVal) {
std::cout << "Constructor Called" << std::endl;
}
int CTest::getValue() {
std::cout << "getValue Called" << std::endl;
return value;
}
int CTest::CTESTSTRUCT::structValue() {
std::cout << "CTESTSTRUCT::setValue Called" << std::endl;
return CTESTSTRUCT::CTESTUNION::var1;
}
CTest::~CTest() {
std::cout << "Distructor Called" << std::endl;
}
//*********************************************************************************
#include <iostream>
#include "CTest.h"
using namespace std;
CTest * ctestObj;
int main() {
ctestObj = new CTest(25);
int returnVal = ctestObj->getValue();
std::cout << "Value Returned: " << returnVal << std::endl;
std::cout << "structVal: " << std::endl;
//CTest::CTESTSTRUCT::testVal = 10;
delete ctestObj;
return 0;
}
What you're actually trying to do is have an instance of a struct inside your class. What you did was define a class within your class (which did not actually give your class a member of that type, but only scoped its definition).
So what you need to do is pull our the struct, from the class:
struct CTESTSTRUCT
{
// ...
};
And then give CTest a member of type CTESTSTRUCT
class CTest {
int value;
public:
CTest(int);
int getValue();
CTESTSTRUCT test;
~CTest();
};
Now you can access it like so:
int main() {
CTest * ctestObj;
ctestObj = new CTest(25);
int returnVal = ctestObj->getValue();
std::cout << "Value Returned: " << returnVal << std::endl;
std::cout << "structVal: " << std::endl;
ctestObj->test.testVal = 10;
delete ctestObj;
return 0;
}

bcc32: strange error when specialising on `std::vector<bool>`

The classic 32-bit Borland/Embarcadero compiler - a.k.a. bcc32 - exhibits a strange failure when a traits class is specialised for std::vector<bool>. In particular, it fails to compile usages of the specialisation because it doesn't find any of its members. With other types - like std::vector<char> - there is no problem at all. Tested with BC++ 5.5.1 (free) and BC++ 7.1 (RX/Seattle).
Is there a workaround for this?
#include <iostream>
#include <typeinfo>
#include <vector>
template<typename T>
struct traits { };
template<> struct traits< std::vector<char> >
{
enum { ENUM = 42 };
static int func () { return ENUM; }
};
template<> struct traits< std::vector<bool> >
{
enum { ENUM = 666 };
static int func () { return ENUM; }
};
///////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T>
void test ()
{
typedef traits<T> TT;
// separate lines to see exactly where the compiler barfs
std::cout << typeid(T).name();
std::cout << " " << TT::ENUM; // E2451 Undefined symbol 'ENUM'
std::cout << " " << TT::func(); // E2451 Undefined symbol 'func'
TT tt;
std::cout << " " << tt.ENUM; // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
std::cout << " " << tt.func(); // E2316 'func' is not a member of 'traits<std::_Bvector>'
std::cout << "\n";
}
int main ()
{
test< std::vector<char> >();
test< std::vector<bool> >();
return 0;
}
Note: a somewhat hackish workaround that can be useful in certain circumstances is to code the specialisation for vector<bool> into the primary template (which would normally be left undefined); the specialisations on other types can then be done as usual, and the code works as expected even with bcc32.
A runtime assert can verify that the only unspecialised incarnation of the traits template is the one for std::vector<bool>. Templates that use the traits would then invoke the assertion code in a convenient place (which could also be a static function).
template<typename T>
struct traits
{
// specialisation for std::vector<bool> coded here...
enum { ENUM = 666 };
static int func () { return ENUM; }
static void assert_only_vector_bool_not_specialised ()
{
assert(typeid(T) == typeid(std::vector<bool>));
}
};
struct traits_specialisation_base
{
static void assert_only_vector_bool_not_specialised ()
{
}
};
template<> struct traits< std::vector<char> >: traits_specialisation_base
{
enum { ENUM = 42 };
static int func () { return ENUM; }
};
// ...
template<typename T>
struct UsingTraits
{
typedef traits<T> TT;
UsingTraits ()
{
TT::assert_only_vector_bool_not_specialised();
}
};
// ...
UsingTraits< std::vector<char> > erna;
UsingTraits< std::vector<bool> > fred;
There is something fishy in the std:: with std::vector<bool> so you need to use the std:: type instead. just change to:
#include <iostream>
#include <typeinfo>
#include <vector>
//---------------------------------------------------------------------------
template<typename T> struct traits
{
// this is safe constructor/destructor for Borland BDS2006 and later
traits(){};
traits(traits& a){};
~traits(){};
traits* operator = (const traits *a){};
//traits* operator = (const traits &a){}; // use this only if you have dynamic allocation members
};
template<> struct traits< std::vector<char> >
{
enum { ENUM = 42 };
static int func () { return ENUM; }
};
template<> struct traits< std::_Bvector > // here use the std type directly
{
enum { ENUM = 666 };
static int func () { return ENUM; }
};
//---------------------------------------------------------------------------
template<typename T> void test ()
{
typedef traits<T> TT;
// separate lines to see exactly where the compiler barfs
std::cout << typeid(T).name();
std::cout << " " << TT::ENUM; // E2451 Undefined symbol 'ENUM'
std::cout << " " << TT::func(); // E2451 Undefined symbol 'func'
TT tt;
std::cout << " " << tt.ENUM; // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
std::cout << " " << tt.func(); // E2316 'func' is not a member of 'traits<std::_Bvector>'
std::cout << "\n";
// can ignore this ... it is just output to memo I do not use console
AnsiString s="";
s=s+typeid(T).name() + "\n";
s=s+" " + AnsiString( TT::ENUM ) + "\r\n"; // E2451 Undefined symbol 'ENUM'
s=s+" " + AnsiString( TT::func() ) + "\r\n"; // E2451 Undefined symbol 'func'
s=s+" " + AnsiString( tt.ENUM ) + "\r\n"; // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
s=s+" " + AnsiString( tt.func() ) + "\r\n"; // E2316 'func' is not a member of 'traits<std::_Bvector>'
Form1->mm_log->Lines->Add(s);
}
//---------------------------------------------------------------------------
// this is your main()
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
{
test< std::vector<char> >();
test< std::vector<bool> >();
}
//---------------------------------------------------------------------------
I use windows form app so ignore form stuff. The constructors/destructors are not necessary for compilation but you should add them because of the Borland BDS2006 and latter C++ engine bug. For more info see:
BDS 2006 C hidden memory manager conflicts
Too many initializers error for a simple array in bcc32
The code above gives me this output:
std::vector<char,std::allocator<char> >
42
42
42
42
std::vector<std::allocator<bool> >
666
666
666
666

Separate Compilation of template with non-type argument

I'm trying to do separate compilation of my non-type argument template, but I am facing a few problems. My application has a number of opcodes, and each opcode is associated with certain data and functions, many of which are similar and could be defined in the primary template, then the differences can be put into specialized templates.
So here is the original in-line code:
(header)
#include <iostream>
template<int opcode>
class BAR
{
public:
BAR(){};
void foo()
{
std::cout << "BAR<int>::foo()" << std::endl;
}
};
// specialize 1 and 2, otherwise we go with the
// primary definition.
template <>
void BAR<1>::foo()
{
std::cout << "BAR<1>::foo()" << std::endl;
}
template <>
void BAR<2>::foo()
{
std::cout << "BAR<2>::foo()" << std::endl;
}
I have a simple 'main':
int main(int argc, char* argv[])
{
BAR<1> bar_1;
BAR<2> bar_2;
BAR<3> bar_3;
bar_1.foo();
bar_2.foo();
bar_3.foo();
return 0;
}
I managed to put the specializations for '1' and '2' into a cpp file and this is
what I have:
(header)
#include <iostream>
template<int opcode>
class BAR
{
public:
BAR(){};
void foo()
{
std::cout << "BAR<int>::foo()" << std::endl;
}
};
// specialize 1 and 2, otherwise we go with the
// primary definition.
template<> void BAR<1>::foo() ;
template<> void BAR<2>::foo() ;
(cpp)
#include "Foo.h"
#include <iostream>
template<> void BAR<1>::foo()
{
std::cout << "BAR<1>::foo()" << std::endl;
}
template<> void BAR<2>::foo()
{
std::cout << "BAR<2>::foo()" << std::endl;
}
void x()
{
BAR<1> b1;
BAR<2> b2;
b1.foo();
b2.foo();
}
I not real crazy about the x() function, but without this I get unresolved symbols for BAR<1>::foo() & BAR<2>::foo(), if there's a better way, I'd be interested ( MSVC 13 compiler).
Ok so far so good. I really want to put the primary definition of the function foo() into the CPP, but I can't seem to get the syntax right:
template<> void BAR<int>::foo()
{
std::cout << "BAR<int>::foo()" << std::endl;
}
this is not allowed by the compiler, and rightly so I guess, is not
a valid non-type value. So what is the magic words to use to do this?
Many thanks in advance for any help.
dave.

Template function is_same in template classes

Why this code produces a false output?
//this-type.cpp
#include <iostream>
#include <type_traits>
using namespace std;
template<typename testype>
class A
{
public:
A()
{
cout << boolalpha;
cout << is_same<decltype(*this), A<int>>::value << endl;
}
};
class B : public A<int>
{
};
int main()
{
B b;
}
Output:
$ g++ -std=c++11 this-type.cpp
$ ./a.out
false
The type of "*this" inside A through B is A< int >, isn't it?
*this is an lvalue of type A, so decltype(*this) will give the reference type A &. Recall that decltype on an lvalue gives the reference type:
cout << is_same<decltype(*this), A<int>>::value << endl;
cout << is_same<decltype(*this), A<int> &>::value << endl;
Output:
false
true
Try:
typedef std::remove_reference<decltype(*this)>::type this_type;
cout << is_same<this_type, A<int>>::value << endl;
and maybe remove_cv in some other contexts (if you don't care about const/volatile) like this:
typedef std::remove_reference<decltype(*this)>::type this_type;
typedef std::remove_cv<this_type>::type no_cv_this_type;
cout << is_same<no_cv_this_type, A<int>>::value << endl;
Are you sure decltype(*this) is A ? You should investigate on that with an ugly cout debug line.