I am trying to use the scoped!T() template to allocate inside the Program class to save on an allocation. I can't get it working with the following exception.
Error: cannot cast &Scoped([void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void]).Scoped_store to ulong at compile time
I'm not shure if it is by design that one cannot use scoped for a class member or if it is an erorr in the scoped template. If its by design than this is a really crappy error message by the way.
The following code is to demonstrate my problem.
import std.typecons;
public class Foo
{
int i = 0;
}
public class Program
{
auto myFoo = scoped!Foo();
}
void main(string[] argv)
{
new Program();
}
auto myFoo = scoped!Foo();
This line will attempt to instantiate a Foo class and initialize the myFoo field during compilation. This is because scoped!Foo() is interpreted as a default value, which are always computed during compilation, therefore the compiler attempts to interpret this expression (CTFE). Because scoped does some low-level things to work, CTFE doesn't work in this case.
Instead, you should initialize the field at runtime, during class construction:
public class Program
{
typeof(scoped!Foo()) myFoo;
this()
{
myFoo = scoped!Foo();
}
}
The scoped documentation actually covers this case. Quoting it:
Scoped member variables must have
type typeof(scoped!Class(args)), and be initialized with a call to
scoped. See below for an example.
And here is the referenced example:
class A
{
int x;
this() {x = 0;}
this(int i){x = i;}
~this() {}
}
// ...
// Use as member variable
struct B
{
typeof(scoped!A()) a; // note the trailing parentheses
this(int i)
{
// construct member
a = scoped!A(i);
}
}
Related
I am trying to figure out what's wrong with this code:
#include <string>
struct Bar
{
using Deduced = typename std::string;
};
class Test
{
template<typename Foo>
auto Func() -> decltype(Foo::Deduced)
{
return Foo::Deduced();
}
};
int main()
{
Test t;
std::string ret = t.template Func<Bar>();
}
I am refactoring a class where Func return type was declared as a template class parameter of Test class, but I would like to change this to work as a member template parameter.
Is this possible?
If yes, anyone could suggest me the right syntax?
Remove the decltype.
decltype gives the type of an expression. But Foo::Deduced is already a type, so you can't apply decltype to it. You simply want to refer to that type itself. So all you have to do is write Foo::Deduced.
However, in some contexts, you need to prefix it with typename to tell the compiler that it's really a type. In C++20, you need typename in return Foo::Deduced() but you don't need it in the trailing return type. Prior to C++20, it was needed in both places. Thus your code could be rewritten like so:
template<typename Foo>
auto Func() -> Foo::Deduced
{
return typename Foo::Deduced();
}
Or a deduced return type could be used:
template<typename Foo>
decltype(auto) Func() // notice no trailing return type
{
return typename Foo::Deduced();
}
In this alias declaration
using Deduced = typename std::string;
the keyword typename is redundant. Just write
using Deduced = std::string;
The template function Func is a private member function of the class Test. You need to make it public.
The decltype specifier expects an expression. You should write at least like
auto Func() -> typename Foo::Deduced
If you have a pointer to a member function like so:
struct Foo { void func() {} };
void(Foo::*funcPtr)() = &Foo::func;
Is there a way to get the type of the function, with the Foo:: removed?
I.e.,
void(Foo::*)() -> void(*)()
int(Foo::*)(int, double, float) -> int(*)(int, double, float)
You get the idea.
The goal is to make std::function accept a functor like this:
struct Functor { void operator()(...){} }
Functor f;
std::function< magic_get_function_type< decltype(Functor::operator()) >::type > stdfunc{f};
Is it possible?
To answer your question, it is possible with a simple template:
template <typename Return, typename Class, typename... Args>
Return(*GetSig(Return(Class::*)(Args...)))(Args...);
This defines a function called GetSig that takes as parameter a member function pointer and essentially extracts the Return type and the Args... and returns it as a non-member function pointer.
Example usage:
class C;
int main() {
using FuncType = int(C::*)(double, float);
FuncType member_pointer;
decltype(GetSigType(member_pointer)) new_pointer;
// new_pointer is now of type int(*)(double, float) instead of
// int(C::*)(double, float)
}
I am trying to understand the difference between function types <void()> and function pointer types <void (*)()>
stl::function can point to functions through <void()>, but I seem to need to use <void (*)()> in my own template classes:
void f1() {
std::cout << "hi!\n";
}
template<class T> struct X
{
T t;
};
int main()
{
std::function<void()> f = f1; // stl handles this, and f is callable
f(); // OK
// X<void()> x; // compilation error - a member of a class template cannot aquire a function type
X<void (*)()> x2; // OK
x2.t = f1; // OK
x2.t(); // OK
return 0;
}
Are function types such as <void()> new to C++ 11, and introduced along with std::function?
I have seen some other questions regarding this, but have not found an explanation which is clear to me, and searching the web for C++ function type does not yield satisfactory results.
I would greatly appreciate any clear explanation or references to one.
Function types aren’t new to C++11 at all: the existed even in C. However, you cannot have objects of function types, i.e.,
template <typename T>
struct X {
T t;
};
X<void()> does_not_work;
X<void(*)()> works;
However, you can turn a function type into a pointer type:
template <typename T>
struct X {
T* t;
};
Upon using a function differently than calling it the function decays into a function pointer. Decaying a function into a pointer is equivalent to taking the function’s address.
Of course, what std::function<...> does is quite different anyway: it actually defines a function call operator. To do so it deckares a general template and specializes it for function types:
template <typename> class function;
template <typename R, typename... A>
class function<R(A...)> {
public:
R operator()(A...);
// ...
};
You can't store a function in a variable, you can only store a function pointer. What is slightly confusing is that the language automatically converts a function into a function pointer when you try to assign the function name to a variable.
Your class would have to be:
template<class T> struct X
{
T* t;
};
To make X<void()> x work. This would of course stop X<void (*)()> x2 from working, you'd have to specialise the template for different types.
Consider this template function:
template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
return fun();
}
Why isn't it possible for the compiler to deduce ReturnT from the passed call signature?
bool bar() { /* ... */ }
foo<bool>(bar); // works
foo(bar); // error: no matching function call
A function pointer of type bool (*)() can be converted to std::function<bool()> but is not the same type, so a conversion is needed. Before the compiler can check whether that conversion is possible it needs to deduce ReturnT as bool, but to do that it needs to already know that std::function<bool()> is a possible conversion, which isn't possible until it deduces ReturnT ... see the problem?
Also, consider that bool(*)() could also be converted to std::function<void()> or std::function<int()> ... which should be deduced?
Consider this simplification:
template<typename T>
struct function
{
template<typename U>
function(U) { }
};
template<typename T>
void foo(function<T>)
{ }
int main()
{
foo(1);
}
How can the compiler know whether you wanted to create function<int> or function<char> or function<void> when they can all be constructed from an int?
std::function<bool()> bar;
foo(bar); // works just fine
C++ can't deduce the return type from your function bar because it would have to know the type before it could find all the constructors that take your function pointer.
For example, who's to say that std::function<std::string()> doesn't have a constructor taking a bool (*)()?
The function bar is of type bool (*)() or so, that is: a normal pre-C++11 function type. I'm not that confident in C++11, but I guess the compiler does not see the connection between bool (*)() and const std::function<ReturnT()>&, even when the first can be implicitly converted into the second for ReturnT = bool.
C++
I'm trying to implement a function wrapper via a (function object) class (variadic) template. The class has as its only data member a function pointer that is initialized by or assigned the function pointer it is wrapping. The parametrized constructor takes a function pointer and initializes the member by it. The operator() method takes argument(s) (or none) and calls the wrapped function with them. At least that's the idea. I get many errors, which I mark with comments. VC11 (with the November 2012 CTP, to enable variadic templates) gives me error C2091: function returns function in all but one of the marked areas. The last error is different, and I comment its full description in the code. g++ gives mostly the same errors, albeit with different code numbers.
#include <iostream>
template <typename R, typename... Tn>
class func
{
R (*fptr)(Tn...); // C2091
public:
func() : fptr(nullptr) {}
func( R (*f) (Tn...) ) : fptr(f) {} // C2091
R operator()(Tn... args)
{ // C2091
return fptr(args...);
}
func& operator=( R (*f) (Tn...) ) // C2091
{
fptr = f;
return *this;
}
};
int foo(int a, int b)
{
std::cout << "foo\n";
return 0;
}
int main()
{
func<int(int, int)> myfunc;
myfunc = foo; // C2679: binary '=' : no operator found which takes
// a right-hand operand of type 'int (__cdecl *)(int,int)' (or
// there is no acceptable conversion)
}
Why am I getting these errors? For example, I don't see how the parametrized constructor returns anything, or how the declaration of the data member returns anything. Isn't the data member declaration in the form of a function pointer declaration? For example, doesn't int (*g)(int); declare a pointer that points to a function that takes an int and returns an int?
Edit/Addendum:
I see from the answers that int(int, int) is only one type and that I need partial specialization to get the effect I want. But, what produces the error in my code? If I comment out myfunc = foo, I still get the other errors. func<int(int, int)> myfunc; calls the default constructor. typename R gets instantiated to int(int, int), and typename... Tn becomes empty. The data member R (*fptr)(Tn...); becomes R (*fptr)();, and fptr is therefore a function pointer that points to a function that takes zero arguments and returns an R. If R is int(int, int), then is R a function pointer type or a function type? If it's the latter, then I can understand the context of the error message.
int(int, int) is one single type. If you want to pass it like that and unwrap it, you need partial specialization:
template <typename> struct func; // leave undefined
template <typename R, typename ...Args>
struct func<R(Args...)> // specialized for typename = R(Args...)
{
// ...
};
Your class is parameterized by the return value and types of arguments, spelled out separately. But when instantiating, you try to parameterize it by a function type, a la std::function. Make it func<int, int, int> myfunc;. With this change, your code works.
You need partial specialization.
Here's a working example:
template <typename T>
class func;
template <typename R, typename... Tn>
class func<R(Tn...)> {
typedef R (*fptr_t)(Tn...);
fptr_t fptr;
public:
func() : fptr(nullptr) {}
func(fptr_t f) : fptr(f) {}
R operator()(Tn... args) {
return fptr(args...);
}
func& operator=(fptr_t f) {
fptr = f;
return *this;
}
};