Here's the scenario: I'd like to have a host class that can have a variable number of mixins (not too hard with variadic templates--see for example http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). However, I'd also like the mixins to be parameterized by the host class, so that they can refer to its public types (using the CRTP idiom).
The problem arises when trying to mix the two--the correct syntax is unclear to me.
For example, the following code fails to compile with g++ 4.4.1:
template <template<class> class... Mixins>
class Host : public Mixins<Host<Mixins>>... {
public:
template <class... Args>
Host(Args&&... args) : Mixins<Host>(std::forward<Args>(args))... {}
};
template <class Host> struct Mix1 {};
template <class Host> struct Mix2 {};
typedef Host<Mix1, Mix2> TopHost;
TopHost *th = new TopHost(Mix1<TopHost>(), Mix2<TopHost>());
With the error:
tst.cpp: In constructor ‘Host<Mixins>::Host(Args&& ...) [with Args = Mix1<Host<Mix1, Mix2> >, Mix2<Host<Mix1, Mix2> >, Mixins = Mix1, Mix2]’:
tst.cpp:33: instantiated from here
tst.cpp:18: error: type ‘Mix1<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’
tst.cpp:18: error: type ‘Mix2<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’
Does anyone have successful experience mixing variadic templates with CRTP?
The following seems to work. I added Mixins... in the inherited mixin classes which expands the parameter pack inplace. Outside the body of Host template, all template parameters of Host must be specified so Mixins... serves the purpose. Inside the body, just Host is sufficient no need to spell out all its template parameters. Kind of a short hand.
#include <utility>
template <template<class> class... Mixins>
class Host : public Mixins<Host<Mixins...>>...
{
public:
Host(Mixins<Host>&&... args) : Mixins<Host>(std::forward<Mixins<Host>>(args))... {}
};
template <class Host> struct Mix1 {};
template <class Host> struct Mix2 {};
int main (void)
{
typedef Host<Mix1, Mix2> TopHost;
delete new TopHost(Mix1<TopHost>(), Mix2<TopHost>());
}
Related
I would like to define a member function in a class template only if traits contain type and use type as its argument like that:
struct A {};
struct B { using type = int; };
template <typename T>
concept has_type = requires { typename T::type; };
template <typename Traits>
struct Handler
{
void set(typename Traits::type)
requires has_type<Traits>
{}
};
Unfortunately, typename Traits::type is parsed before the requires clause and it fails to compile if type does not exist (struct A):
<source>:19:14: error: no type named 'type' in 'struct A'
19 | void set(typename Traits::type)
I could only come up with this alternative, which looks excessively cumbersome:
template <typename Traits>
struct Handler
{
template <typename Type>
requires has_type<Traits> && std::same_as<Type, typename Traits::type>
void set(Type)
{}
};
It also fails to compile under clang (although I expected it to short-circuit), but gcc compiles it correctly:
<source>:20:78: error: no type named 'type' in 'A'
requires has_type<Traits> && std::same_as<Type, typename Traits::type>
Full example.
Questions
What is the idiomatic way to define set depending on whether Traits class contains type?
Why does clang try to evaluate std::same_as if requires has_type failed?
Who is right, clang or gcc?
A class template member function is constrainable, but is not SFINAE-aware. The idiomatic solution (which, inter alia, works even under C++17) is to make set a (class template member) function template accessing the type member type alias via (type-dependent) SFINAE context:
template<int..., class U = Traits>
void set(typename U::type);
or:
template<std::same_as<Traits> U = Traits>
void set(typename U::type);
Example.
wrt 2., 3., see How to use a trait type as an argument to an optionally compiled member function of a class template?
While working in the system c program I missed out the public keyword before constructor, but the program works fine.
But in C++, its throwing an error
SystemC requires that first parameter to module constructor should be sc_module_name. Other than that, there is nothing special. SystemC macros SC_MODULE and SC_CTOR just save you some time, but you are not required to use them.
SC_MODULE( dut ) {
SC_CTOR(dut) { }
};
Is equivalent to:
struct dut : sc_core::sc_module {
typedef dut SC_CURRENT_USER_MODULE;
dut(::sc_core::sc_module_name) {}
};
Please note that struct members are public by-default, and class members are private by default. If you use class instead of struct, you will need to make them public by adding public: explicitly:
class dut : public sc_core::sc_module {
typedef dut SC_CURRENT_USER_MODULE;
public:
dut(::sc_core::sc_module_name) {}
};
class Test {
int a = 100;
System.out.println(a);
}
class Demo {
public static void main(String args[]) {
Test t = new Test();
}
}
I'm new to programming. I found this code when I'm practicing. I don't understand why I'm getting this error.
Here is the error I'm getting.
Demo.java:3: error: <identifier> expected
System.out.println(a);
^
Demo.java:3: error: <identifier> expected
System.out.println(a);
^
2 errors
Compilation failed.
Can you guys explain why I'm getting this error?
You can't call a method directly from the java class body.
Create a constructor in your Test class, and put the print in it :
class Test {
int a = 100;
public Test() {
System.out.println(a);
}
}
Note that if for some reason you really want a statement to be executed when the class is loaded without using a constructor, you can define a static block, here an example :
class Test {
static int a = 100;
static {
System.out.println(a);
}
}
However, this is just for reference and really not needed in your case.
From Declaring Classes in the Java tutorial:
In general, class declarations can include these components, in order:
Modifiers such as public, private, and a number of others that you will encounter later.
The class name, with the initial letter capitalized by convention.
The name of the class's parent (superclass), if any, preceded by the keyword extends. A class can only extend (subclass) one parent.
A comma-separated list of interfaces implemented by the class, if any, preceded by the keyword implements. A class can implement more than one interface.
The class body, surrounded by braces, {}.
You can't make any function calls outside of a method declaration.
I tried making an extension to the built-in String class using C++/CLI, and using it from C++/CLI without success.
Here's the simplest I can boil it down to:
[System::Runtime::CompilerServices::Extension]
public ref class MyStringExtensions abstract sealed {
public:
[System::Runtime::CompilerServices::Extension]
static bool TestMethod(System::String^ str) { return false; }
};
Now, when I try to use this in other C++/CLI code, I get a compiler message indicating that TestMethod is not a method of String.
String^ foo = gcnew ...
...
blah = foo->TestMethod(); // compile-error
Any ideas?
C++ doesn't have extension methods.
But it does have ADL (Argument-dependent lookup, also known as Koenig lookup) which is arguably even nicer.
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.