#pragma GCC unroll with compile-time argument - g++

Is there a way to unroll a loop in GCC based on compile-time (e.g., template) parameter?
The following does not compile, unless I replace unroll(N) with a concrete integer like unroll(8)
template<int N>
void fun ()
{
#pragma GCC unroll(N)
for (...)
// body
}

Related

Missing a warning on unexpected implicit enum casts

I have made a new Objective-C project in Xcode 10.2.1 (Apple LLVM version 10.0.1 (clang-1001.0.46.4)), and have a code like this inside main.m:
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSUInteger, Fruit) {
Apple,
Banana,
Coconut,
};
void boolArg(BOOL b) { if (b) puts("boolArg"); }
void shortArg(short s) { if (s > 0) puts("shortArg"); }
void fruitArg(Fruit f) { if (f == Banana) puts("fruitArg"); }
int main() {
Fruit f = Coconut;
// NEED WARN: passing Fruit instead of a boolean, unexpected cast
boolArg(f);
// NEED WARN: fruit (NSUInteger) instead of a short, unexpected cast losing precision
shortArg(f);
// NEED WARN: passing boolean instead of a Fruit, unexpected cast
fruitArg(YES);
return 0;
}
In my codebase I'd like to protect from such implicit casts. Is it possible to enable some clang warning to catch this?
What I tried so far and it didn't help:
enabled "Implicit Signedness Conversions" warning;
added to "Other Warnings Flags": -Wall, -Wextra;
change main.m to main.mm (to compile with Objective-C++) - only catches the last fruitArg call.

g++ and omp simd virtual functions

I am having little success forcing g++ to generate vector (aka omp simd) calls to virtual functions. Consider the base class
class vecclass_v {
public:
#pragma omp declare simd simdlen(4)
virtual double vecf(double v1, double v2) = 0;
}
and a derived class that implements the (should be) vectorized vecf
class vecclass : public vecclass_v {
public:
#pragma omp declare simd simdlen(4)
double vecf(double v1, double v2);
};
The implementation is in a cxx file. Looking at the object files I can see that g++ correctly generates instances of vectorized functions for the derived class. But calling the virtual function is not resolved to a vectorized call. It uses the scalar member instance instead, e.g., in a usecase like this one
vecclass_v *ob = [get an instance of vecclass somewhere]
ob->vecf(a, b); // this should be vectorized, but is not
The Intel compiler does support vectorized virtual functions (https://software.intel.com/en-us/articles/virtual-vector-function-supported-in-intel-c-compiler-170). Does g++ support this, but I just can't use it, or is this not implemented yet?

Mixed C++/CLI overloading

Is this a proper restriction on overloading behavior. I can't figure out how to replicate a similar issue in pure C++ to compare behavior.
C++/CLI code:
class A {};
List<int>^ g(A &) {
return gcnew List<int>();
}
template<typename T>
List<T>^ g(T &) {
return gcnew List<T>();
}
void f() {
g(A()); // compiler error C3235
}
Generates:
error C3225: generic type argument for 'T' cannot be 'A', it must be a
value type or a handle to a reference type
The problem appears to be from the return values. It's requiring that the templated g() has a valid definition even though the non-templated g() overload should (shouldn't it?) be selected.

Obj-C++: template metafunction for recognizing Objective-C classes?

Using Objective-C++, can I write a C++ IsObjectiveCClass<T> template metafunction such that IsObjectiveCClass<T>::value is true if and only if T is an Objective-C class?
Exactly what are ObjC classes from the viewpoint of the C / C++ subset of the language? When used in a C / C++ context, MyClass* pointers seem to behave like ordinary C pointers; does that mean that MyClass is also a C type?
Here is a simplistic solution that should work in most (if not all? Can anyone think of when this might fail?) cases (it uses clang 3.0 via xcode 4.2 - use typedefs instead of using aliases for earlier clang versions):
template<class T> struct IsObjectiveCClass
{
using yesT = char (&)[10];
using noT = char (&)[1];
static yesT choose(id);
static noT choose(...);
static T make();
enum { value = sizeof(choose(make())) == sizeof(yesT) };
};
You can read my most recent rant about ObjC++ in this question. Avoid it as much as you can possibly get away with. Definitely don't try to integrate Objective-C into C++ template metaprogramming. The compiler might actually rip a hole in space.
Hyperbole aside, what you're trying to do is likely impossible. Objective-C classes are just structs. (C++ classes actually just structs too.) There's not much compile-time introspection available.
An id is a C pointer to a struct objc_object. At runtime, every object is an id, no matter its class.
typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id;
As with the accepted answer, you can test whether the type is convertible to id, in C++17:
template <typename T>
struct is_objc_ptr : std::integral_constant<bool,
std::is_convertible_v<T, id> && !std::is_null_pointer_v<T>> {};
template <typename T>
constexpr bool is_objc_ptr_v = is_objc_ptr<T>::value;
Testing:
static_assert(!is_objc_ptr_v<nullptr_t>);
static_assert(!is_objc_ptr_v<int>);
static_assert(!is_objc_ptr_v<char *>);
static_assert(is_objc_ptr_v<id>);
static_assert(is_objc_ptr_v<NSObject *>);
I don't know of a way to discover ObjC inheritance relationships at compile-time; in theory they're changeable at runtime so you would have to query the runtime.
If you look at the implementation of the C++ STL library in Xcode, you can follow the template specialization models of others like std::is_integral or std::is_floating_point:
template <class T> struct isObjcObject : public std::false_type { };
template <> struct isObjcObject<id> : public std::true_type { };
where std::false_type and std::true_type are defined in the <type_traits> header file.
If for whatever reason you don't have std::false_type and std::true_type (depending on your C++ version), you can define them yourself as such:
template<bool B> struct boolean_constant { static constexpr const bool value = B; };
template <class T> struct isObjcObject : public boolean_constant<false> { };
template <> struct isObjcObject<id> : public boolean_constant<true> { };
Note that you can also do this for Objective-C classes too:
template <class T> struct isObjcClass : public std::false_type { };
template <> struct isObjcClass<Class> : public std::true_type { };
I would create a template specialisation for 'id' and 'NSObject*', but you'll always be working against the language because the ObjC type system is not the C++ type system.
Similar to Doug's answer, but slightly simpler:
template<typename T>
inline constexpr bool is_objc_v = std::is_convertible_v<id,T>;
Checking that id is convertible to T – instead of the other way around – avoids false positives for C++ types which have a user-defined implicit conversion to an Obj-C type.

What header file needs to be included for using nullptr in g++?

I am using g++ 4.4.1 and want to use nullptr, but I am not being able to find which header file is required to be included. It does not seem to be keyword either, because my attempt to use it is rejected as
error: 'nullptr' was not declared in this scope
GCC 4.4.1 does not support nullptr.
Support for nullptr was added in GCC 4.6.0:
http://gcc.gnu.org/gcc-4.6/changes.html
Improved experimental support for the
upcoming C++0x ISO C++ standard,
including support for nullptr (thanks
to Magnus Fromreide), noexcept,
unrestricted unions, range-based for
loops (thanks to Rodrigo Rivas Costa),
implicitly deleted functions and
implicit move constructors.
For earlier versions of GCC, if you want to experiment with nullptr you can try the workaround in this SO question:
Can nullptr be emulated in GCC?
I would recommend not using nullptr as defined above, because it can be dangerous. If you want to use nullptr the following statement should be true.
sizeof(nullptr) == sizeof(void*) == sizeof(any pointer)
However, sizeof(nullptr) (as defined above) will not comply to this rule. It will actually evaluate to sizeof(bad nullptr) = 1.
This is a correct implementation.
#pragma once
namespace std
{
//based on SC22/WG21/N2431 = J16/07-0301
struct nullptr_t
{
template<typename any> operator any * () const
{
return 0;
}
template<class any, typename T> operator T any:: * () const
{
return 0;
}
#ifdef _MSC_VER
struct pad {};
pad __[sizeof(void*)/sizeof(pad)];
#else
char __[sizeof(void*)];
#endif
private:
// nullptr_t();// {}
// nullptr_t(const nullptr_t&);
// void operator = (const nullptr_t&);
void operator &() const;
template<typename any> void operator +(any) const
{
/*I Love MSVC 2005!*/
}
template<typename any> void operator -(any) const
{
/*I Love MSVC 2005!*/
}
};
static const nullptr_t __nullptr = {};
}
#ifndef nullptr
#define nullptr std::__nullptr
#endif
I use -std=c++0x to enable the nullptr feature with gcc 4.6.3
If you don't have the latest gcc which supports C++11 , try using NULL instead of nullptr.