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
}
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.
I have some swift code, which is not really important in context of question.
Also i have Objective-C bridging header ObjC-Swift-Bridging.h:
#import "my_objective_cpp_header.h"
And i have free C/C++ - style functions in that header:
inline void foo() {
}
inline void foo(int i) {
}
When i try to compile it in xcode 9.2 with enabled swift 4.0 i get error:
my_objective_cpp_header.h:29:13: error: redefinition of 'foo'
inline void foo(int i){
^
my_objective_cpp_header.h:26:13: note: previous definition is here
inline void foo() {
^
ObjC-Swift-Bridging.h:22:9: note: in file included from ObjC-Swift-Bridging.h:22:
#import "my_objective_cpp_header.h"
The same happens if i put these functions to C/C++ header and write
#include "my_cpp_header.h"
into ObjC-Swift-Bridging.h
So... Swift doesn't support code which was supported in Objective-C++? Did i miss something?
I have following code
ref class A
{
typedef ref struct All
{
std::string x;
}All_t;
};
in my program I am using it in following manner
A::All_t t;
t.X = "H";
This declaration throwing error as
error C4368: cannot define 'x' as a member of managed 'A::All': mixed types are not supported
I understand that I am declaring native varible inside managed code which is not allowed but now I would like to know changes I will need to make to make my structure suitable to managed project.
Thanks.
I'm assuming you originally had std::string x; not std::string *x (since using the pointer to string does not generate that error). You are not allowed to directly embed a native type in a managed type, but you are allowed to indirectly have one (via a pointer) See:
http://msdn.microsoft.com/en-us/library/xhfb39es(v=vs.80).aspx
After I fixed the compiler errors in your sample, it builds without error:
#include "stdafx.h"
#include <string>
using namespace System;
ref class A
{
public:
typedef ref struct All
{
std::string * x;
}All_t;
};
int main(array<System::String ^> ^args)
{
A::All_t t;
t.x = new std::string("H");
return 0;
}
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.