Due to some legacy reasons I'm stuck with MIPS-GCC 4.5.3. But the code which I'm trying to compile uses C++11 nullptr & nullptr_t heavily which is a missing feature in GCC 4.5.3.
After some googling & getting into the usage I ended up creating a nullptr wrapper like below, but unfortunately it doesn't satisfy some of the use case,
namespace std {
class nullptr_t {
public:
nullptr_t() { }
template <typename T> nullptr_t(const T&) { }
template <class T> nullptr_t(const T*) { }
template <class T> nullptr_t(T*) { }
template <typename T, typename U> nullptr_t(const typename T::U*) { }
template<typename T> operator T*() { return 0;}
template<typename T1, typename T2> operator T1 T2::*() { return 0; }
operator int() const { return 0; }
operator unsigned() const { return 0; }
operator bool() const { return false; }
bool operator == (unsigned i) const { return i == 0; }
bool operator != (unsigned i) const { return i != 0; }
bool operator !() const { return true; }
} nullptr = {};
}
using std::nullptr;
template<typename T> struct DummyContainer {
DummyContainer(T* ptr)
: m_ptr(ptr) { }
DummyContainer(std::nullptr_t)
: m_ptr(0) { }
T& operator = (std::nullptr_t) { return *m_ptr; }
private: T* m_ptr;
};
int main(int argc, char** argv)
{
const char* case1 = nullptr; // working
// I think for below case std::unique_ptr has to be modified to take std::nullptr_t during construction & operator =
std::unique_ptr<char> case2 = nullptr; // not working.
DummyContainer<char> case3 = nullptr; // working
case3 = nullptr; //working
unsigned* case4 = argc > 1 ? nullptr : nullptr; //works
unsigned* case5 = argc > 2 ? (unsigned*)0 : nullptr; //not working. (It is the major issue as of now)
return 0;
}
Here the major case is unsigned* case5 = argc > 2 ? (unsigned*)0 : nullptr;
IDEONE snapshot : http://ideone.com/m1mhtB
(Thanks to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf)
Any tips/suggestions will be appreciated :)
(Note: please avoid answers like upgrade your gcc)
Below solution seems to be working,
Original source: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/WebKit/Source/wtf/NullPtr.h
namespace std {
class nullptr_t {
public:
// Required in order to create const nullptr_t objects without an
// explicit initializer in GCC 4.5, a la:
//
// const std::nullptr_t nullptr;
nullptr_t() { }
// Make nullptr convertible to any pointer type.
template<typename T> operator T*() const { return 0; }
// Make nullptr convertible to any member pointer type.
template<typename C, typename T> operator T C::*() { return 0; }
private:
// Do not allow taking the address of nullptr.
void operator&();
};
}
const std::nullptr_t nullptr;
IDEOne: http://ideone.com/Bnp6th
Related
Maybe I don't know something about C++, but I found incomprehensible (and dangerous in my opinion) C++ compiler behavior.
MSVC, g++ and Clang behave the same.
Q: Why function ::a::f is visible as f inside b::f(bool)?
namespace a {
struct C {
bool value;
C(): value(false) {}
C(C const &): value(false) {}
explicit C(bool value): value(value) {}
};
inline C f(bool value) { return C(value); }
// why this function is visible as `f` inside `b::f(bool)`?
inline C f(C const &value) { return C(not value.value); }
}
namespace b {
inline bool f(::a::C const &value) { return value.value; }
inline bool f(bool value) {
#ifdef WORK_AROUND_PROBLEM
return b::f(a::f(value));
#else
// why `::a::f` is visible as `f` here?
return f(a::f(value)).value;
#endif
}
}
int main(int, char **) {
if (b::f(false) or (! b::f(true))) return 1;
if (b::f(0)) return 2;
if (b::f(a::C(false)) || (! b::f(a::C(true)))) return 3;
return 0;
}
======== UPDATE ========
First code example can be explained with Argument dependent lookup https://en.cppreference.com/w/cpp/language/adl. Thanks for the answers. =)
But it's still not clear to me how to properly deal with set of "universal functions". In context of first example I cannot figure out how to properly replace f (C const &) with template <class ... T> auto f (T && ...)
As next example [c++20], I've posted a piece of more real code (but simplified) here.
This is a part of header-only library. Here I would like to have a universal make function for the ::exception::Walker. And a universal make function for exception::Backtrace. Moreover, I would like to have minimal connectivity between ::exception::walker and ::exception::backtrace namespaces. See comments in the code below.
#include <cstdint>
#include <list>
#include <ranges>
#include <utility>
#include <iterator>
#include <iostream>
#include <algorithm>
#include <exception>
#include <stdexcept>
#include <type_traits>
// from <.../exception/walker.fwd.hpp>
namespace exception {
namespace walker {
struct Class;
struct Iterator;
using Value = ::std::exception_ptr;
template <class ... T> auto make(T && ...);
} // namespace walker
using Walker = walker::Class;
} // namespace exception
// from <.../exception/backtrace.fwd.hpp>
namespace exception {
namespace backtrace {
using Item = ::std::exception_ptr;
using Class = ::std::vector<Item>;
auto make();
template <class T> auto make(T &&source);
template <class beginT, class endT> auto make(beginT &&begin, endT &&end);
} // namespace backtrace
using BackTrace = backtrace::Class;
} // namespace exception
// from <.../exception/walker.hpp>
namespace exception::walker {
struct Class final {
using Value = walker::Value;
using Iterator = walker::Iterator;
auto begin() const noexcept(true);
auto end() const noexcept(true);
Class() noexcept(true) = default;
Class(Class &&) noexcept(true) = default;
Class(Class const &) noexcept(true) = default;
template <class headT, class ... tailT> requires((0 < sizeof ... (tailT)) or (not ::std::is_base_of_v<Class, ::std::decay_t<headT>>))
explicit Class(headT &&head, tailT && ... tail) noexcept(true);
private:
Value last_;
// There was a lot of overloads
template <class T> decltype(auto) make_value_(T &&value) noexcept(true);
};
struct Iterator final {
using iterator_category = ::std::input_iterator_tag;
using difference_type = ::std::ptrdiff_t;
using value_type = Value;
using pointer = Value *;
using reference = Value &;
inline auto & operator*() const noexcept(true) { return value_; }
inline auto * operator->() const noexcept(true) { return &value_; }
inline auto & operator++() noexcept(true) {
auto const temporary_ = value_;
if (static_cast<bool>(temporary_)) {
value_ = {};
try { ::std::rethrow_exception(temporary_); }
catch(::std::exception const &exception_) {
try { ::std::rethrow_if_nested(exception_); }
catch (...) { value_ = ::std::current_exception(); }
}
catch (...) {}
}
return *this;
}
inline auto operator++(int) noexcept(true) { auto const temporary_ = *this; ++(*this); return temporary_; }
inline auto operator==(Iterator const &other) const noexcept(true) { return value_ == other.value_; };
inline auto operator!=(Iterator const &other) const noexcept(true) { return not (*this == other); };
Iterator & operator=(Iterator &&) noexcept(true) = default;
Iterator & operator=(Iterator const &) noexcept(true) = default;
Iterator() noexcept(true) = default;
Iterator(Iterator &&) noexcept(true) = default;
Iterator(Iterator const &) noexcept(true) = default;
inline explicit Iterator(Value const &value) noexcept(true): value_{value} {}
private:
value_type value_;
};
inline auto Class::begin() const noexcept(true) { return Iterator{last_}; }
inline auto Class::end() const noexcept(true) { return Iterator{}; }
template <class T> inline decltype(auto) Class::make_value_(T &&value) noexcept(true) {
if constexpr (::std::is_same_v<::std::exception_ptr, ::std::decay_t<decltype(value)>>) return ::std::forward<decltype(value)>(value);
else return ::std::make_exception_ptr(::std::forward<decltype(value)>(value));
}
template <class headT, class ... tailT> requires((0 < sizeof ... (tailT)) or (not ::std::is_base_of_v<Class, ::std::decay_t<headT>>))
inline Class::Class(headT &&head, tailT && ... tail) noexcept(true): last_{::exception::walker::Class::make_value_(::std::forward<headT>(head), ::std::forward<tailT>(tail) ...)} {}
template <class ... T> inline auto make(T && ... payload) { return Class{::std::forward<T>(payload) ...}; }
} // namespace exception::walker
// from <.../exception/backtrace.hpp>
namespace exception::backtrace {
namespace private_ {
// in fact, it would be more correct to use const lvalue to T (T const &source) instead universal reference (T &&), but then
// ::other::namespace::make function may be used (::exception::walker::make for example if ::std::decay_t<sourceT> will be ::exception::walker::Class)
template <class sourceT> inline auto make(void const *, sourceT const &source) {
using CollectorItem = ::std::decay_t<decltype(*::std::begin(source))>;
auto collector_ = ::std::list<CollectorItem>{};
auto size_ = static_cast<::std::size_t>(0);
for (auto const &exception_ : source) { size_++; collector_.push_front(exception_); }
auto result_ = Class(size_);
::std::copy(collector_.begin(), collector_.end(), result_.begin());
return result_;
}
template <class T> inline auto make(::std::exception const *, T &&exception) {
// sad, but without knowledge about content of namespace in which the real type of T is located, I have to write here explicitly ::exception::backtrace::private_::make
return ::exception::backtrace::private_::make(static_cast<void const *>(nullptr), ::exception::walker::make(::std::forward<T>(exception)));
}
template <class T> inline auto make(::std::exception_ptr const *, T &&exception) {
// sad, without knowledge about content of namespace in which the real type of T is located, I have to write here explicitly ::exception::backtrace::private_::make
return ::exception::backtrace::private_::make(static_cast<void const *>(nullptr), ::exception::walker::make(::std::forward<T>(exception)));
}
} // namespace private_
template <class T> inline auto make(T &&source) {
// sad, but without knowledge about content of namespace in which the real type of T is located, I have to write here explicitly ::exception::backtrace::private_::make
return ::exception::backtrace::private_::make(static_cast<::std::decay_t<T> const *>(nullptr), ::std::forward<T>(source));
}
template <class beginT, class endT> inline auto make(beginT &&begin, endT &&end) {
// sad, but without knowledge about content of namespace in which the real type of ::std::ranges::subrange result is located, I have to write here explicitly ::exception::backtrace::make
return ::exception::backtrace::make(::std::ranges::subrange(::std::forward<beginT>(begin), ::std::forward<endT>(end)));
}
} // namespace exception::backtrace
namespace test_ {
inline static auto internal() { throw ::std::runtime_error{"internal function error"}; }
inline static auto external() {
try { internal(); }
catch(...) { ::std::throw_with_nested(::std::runtime_error{"external function error"}); }
}
}
int main(int, char **) {
try { test_::external(); }
catch(...) {
for (auto const &exception_: ::exception::backtrace::make(::std::current_exception())) {
try { ::std::rethrow_exception(exception_); }
catch(::std::exception const &exception_) { ::std::clog << exception_.what() << ::std::endl << ::std::flush; }
catch(...) { ::std::clog << "unknown exception" << ::std::endl << ::std::flush; }
}
}
return 0;
}
This is due to Argument dependent lookup.
If a function takes a parameter of a custom type, the namespace that the type is declared in is searched for viable overloads when calling a function.
f(a::f(value))
Is passing a C to f. This triggers ADL, thus additionally to doing name lookup in the surounding scopes, the compiler also searches in namespace a since C is declared there.
This is most commonly an important feature when defining free-function operator overloads. We can put them in the same namespace as the type in question, and ADL will make sure the overload is found at name-lookup without polluting the global/outer scopes.
My template operator is conflicting (overloading) with the bool operator when template type is bool. Any way of getting around this? For example, can I somehow "turn off" the operator T() when T is assigned to bool?
template <typename T = bool>
class MyClass {
public:
operator bool() const { return false; }
operator T() const { return t; }
private:
T t;
};
You can use SFINAE to disable to operator bool when T is a bool like
template <typename T = bool>
class MyClass {
public:
template <typename U = T, typename std::enable_if<!std::is_same<U, bool>::value, bool>::type = true>
operator bool() const { return false; }
operator T() const { return t; }
private:
T t;
};
Another option would be to specialize for bool like
template <typename T = bool>
class MyClass {
public:
operator bool() const { return false; }
operator T() const { return t; }
private:
T t;
};
template <>
class MyClass<bool> {
public:
operator bool() const { return false; }
private:
bool t;
};
You can use SFINAE:
#include <iostream>
#include <type_traits>
template <typename T = bool>
class MyClass {
public:
template<typename U = T,typename = std::enable_if_t<!std::is_same_v<U,bool>,void>>
operator bool() const { return false; }
operator T() const { return t; }
private:
T t = true;
};
int main() {
MyClass mc;
std::cout << static_cast<bool>(mc);
MyClass<int> mc2;
std::cout << static_cast<bool>(mc2);
}
I'm trying to help with this question, and I think I found a nice solution. But it's kind of complex due to all the wrapping I need.
I would want to overload operator>> to allow for easy chaining notation. But it's not working as I expected.
I can do:
#include <functional>
#include <memory>
template<typename T>
class Object {
private:
T* const ptr{ nullptr };
public:
Object(T* ptr) noexcept : ptr(ptr) {}
T* Get() const noexcept { return ptr; }
};
using MyObject = Object<int>;
template <typename T, typename MemFn>
auto fnc (T* ptr, MemFn memFn)
-> decltype(std::invoke(memFn, std::declval<T>())) {
if (ptr) return std::invoke(memFn, *ptr);
return nullptr;
}
int main() {
std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
[[maybe_unused]] int* optionalTarget = fnc(myObjectPtr.get(), &MyObject::Get);
}
However, I want to do
#include <functional>
#include <memory>
template<typename T>
class Object {
private:
T* const ptr{ nullptr };
public:
Object(T* ptr) noexcept : ptr(ptr) {}
T* Get() const noexcept { return ptr; }
};
using MyObject = Object<int>;
template <typename T, typename MemFn>
auto operator>> (T* ptr, MemFn memFn)
-> decltype(std::invoke(memFn, std::declval<T>())) {
if (ptr) return std::invoke(memFn, *ptr);
return nullptr;
}
int main() {
std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
[[maybe_unused]] int* optionalTarget = myObjectPtr.get() >> &MyObject::Get;
}
What does work, but what I consider ugly is
#include <functional>
#include <memory>
#include <optional>
template<typename T>
class Object {
private:
T* const ptr{ nullptr };
public:
Object(T* ptr) noexcept : ptr(ptr) {}
T* Get() const noexcept { return ptr; }
};
using MyObject = Object<int>;
template <typename T>
auto makeOptRef(T* ptr) -> std::optional< std::reference_wrapper<T>> {
if (ptr) return std::ref(*ptr);
return {};
}
template <typename T, typename MemFn>
auto operator>> (std::optional<std::reference_wrapper <T>> ptr, MemFn memFn)
-> std::optional<std::reference_wrapper<std::remove_pointer_t<decltype(std::invoke(memFn, std::declval<T>()))>>> {
if (ptr) return makeOptRef(std::invoke(memFn, *ptr));
return {};
}
int main() {
std::unique_ptr<MyObject> myObjectPtr = std::make_unique<MyObject>(nullptr);
std::optional<std::reference_wrapper<MyObject>> myObjOptRef = makeOptRef(myObjectPtr.get());
std::optional<std::reference_wrapper<int>> optionalTarget = myObjOptRef >> &MyObject::Get;
[[maybe_unused]] int output = (optionalTarget) ? optionalTarget->get() : -1;
}
Any pointer type is a built-in type, as are pointers to members. You are trying to overload an operator for two built-in types, that's simply a non-starter. At least one argument must be of a user-defined type, or a reference to it.
You can get it to work by passing a T& instead of a T*.
I need to use a function template which is available in a header file via a function pointer which is available as a struct member.
For example:
File: mytemplate.h
template<typename T> const bool GT(const T& pa_roIN1, const T& pa_roIN2)
{
bool temp = false;
if(pa_roIN1 > pa_roIN2){
temp = true;
}
return temp;
}
template<typename T> const bool EQ(const T& pa_roIN1, const T& pa_roIN2)
{
bool temp = false;
if(pa_roIN1 == pa_roIN2){
temp = true;
}
return temp;
}
template<typename T> const bool GE(const T& pa_roIN1, const T& pa_roIN2)
{
bool temp = false;
if(pa_roIN1 >= pa_roIN2){
temp = true;
}
return temp;
}
File: mystruct.h:
struct mystruct {
std::string funcName;
bool (*funcPtr)(int,int);
};
typedef std::map<int, mystruct> mystructList;
File: mycpp.cpp:
#include "mytemplate.h"
#include "mystruct.h"
mystruct MyGreaterStruct[3] = {
{"GREATER_THAN", >},
{ "EQUAL", &EQ},
{ "GREATER_N_EQUAL", &GE}
};
mystructList MyList;
int main(void)
{
int size = sizeof(MyGreaterStruct)/sizeof(mystruct);
for(int i = 0; i < size; i++) {
MyList.insert(std::pair<int, mystruct>(i,MyGreaterStruct[i])); }
for(mystructList::iterator iter = MyList.begin(); iter != MyList.end(); iter++) {
printf("\nResult of func : %s for values 100,50 : %d",iter->second.funcName.c_Str(),iter->second->funcPtr(100,50));
}
}
I am not sure this the correct way of doing it. But there is no result that gets printed on the console.
The error you get when compiling your code tells you what is wrong:
mycpp.cpp:8:1: error: no matches converting function ‘GT’ to type ‘bool (*)(int, int)’
};
^
mytemplate.h:1:33: note: candidate is: template<class T> const bool GT(const T&, const T&)
template<typename T> const bool GT(const T& pa_roIN1, const T& pa_roIN2)
^
There's no way to instantiate that template to match the signature of the function pointer, as the template takes two references as arguments, while the pointer takes two ints. If you can't change either the struct or the templates, and you are using C++11, you could try using lambdas instead:
mystruct MyGreaterStruct[3] = {
{"GREATER_THAN", [](int a, int b)->bool { return GT(a, b); } },
{ "EQUAL", [](int a, int b)->bool { return EQ(a, b); } },
{ "GREATER_N_EQUAL", [](int a, int b)->bool { return GE(a, b); } }
};
but no matter how you slice it, you need to either change the arguments or use a little function that converts the arguments from one form to the other.
template<class T>
class auto_ptr2 {
public:
explicit auto_ptr2(T *p = 0): pointee(p) {}
template<class U>
auto_ptr2(auto_ptr2<U>& rhs): pointee(rhs.release()) {}
~auto_ptr2() { delete pointee; }
template<class U>
auto_ptr2<T>& operator=(auto_ptr2<U>& rhs)
{
if (this != &rhs) reset(rhs.release());
return *this;
}
T& operator*() const { return *pointee; }
T* operator->() const { return pointee; }
T* get() const { return pointee; }
T* release()
{
T *oldPointee = pointee;
pointee = 0;
return oldPointee;
}
void reset(T *p = 0)
{
if (pointee != p) {
delete pointee;
pointee = p;
}
}
private:
T *pointee;
//template<class U> friend class auto_ptr2<U>;
// Question 1> Why we have to define this friend class
// Question 2> I cannot compile this code with above line with VS2010.
// Error 1 error C3772: 'auto_ptr2<T>' : invalid friend template declaration
};
thank you
Why we have to define this friend class
I'm fairly sure you don't; as far as I can see, nothing is referencing the private member of a different template instantiation. You would need it if the copy constructor or assignment operator manipulated rhs.pointee directly, rather than just calling rhs.release().
I cannot compile this code with above line with VS2010.
The declaration should be:
template<class U> friend class auto_ptr2;