Trying to use is_class in the following segment (stripped down from a larger one), but it doesn't seem to work. What's wrong?
#include <type_traits>
template<typename U, typename = void>
struct xxxU_Impl
{
static void xxxU_push (const U& value);
};
template<typename U> void xxxU_push (const U& value) { xxxU_Impl<U>::xxxU_push (value); }
template<typename U>
struct xxxU_Impl<U *, typename std::enable_if<std::is_class<U>::value>::type>
{
static void xxxU_push (const U *& value) { }
};
class Foo
{
public:
int mFoo;
};
int main () {
Foo * pFoo = new Foo;
xxxU_push<Foo *>(pFoo);
}
This is with gcc v4.7.2 on cygwin with gcc -std=c++11 test.cpp command line.
The output is:
test.cpp: In instantiation of 'void xxxU_push(const U&) [with U = Foo*]':
test.cpp:26:23: required from here
test.cpp:9:63: error: no matching function for call to 'xxxU_Impl<Foo*, void>::xxxU_push(Foo* const&)'
test.cpp:9:63: note: candidate is:
test.cpp:14:17: note: static void xxxU_Impl<U*, typename std::enable_if<std::is_class<_Tp>::value>::type>::xxxU_push(const U*&) [with U = Foo]
test.cpp:14:17: note: no known conversion for argument 1 from 'Foo* const' to 'const Foo*&'
**
Update
:**
Here's the modified code with annotations which IMHO show that the types are now identical. Still, I'm getting a compile error.
#include <type_traits>
template<typename U, typename = void>
struct xxxU_Impl
{
static void xxxU_push (const U & value); // U=Foo*: const Foo* & value ==
// Foo const * & value
};
template<typename U> void xxxU_push (const U & value) // U=Foo*: const Foo* & value ==
// Foo const * & value
{ xxxU_Impl<U>::xxxU_push (value); }
template<typename U>
struct xxxU_Impl<U *, typename std::enable_if<std::is_class<U>::value>::type>
{
static void xxxU_push (U const * & value) { } // U=Foo: Foo const * & value
};
class Foo
{
public:
int mFoo;
};
int main () {
Foo* pFoo = new Foo;
xxxU_push<Foo*>(pFoo);
}
What's wrong?
Thx,
D
PS A similar scheme with is_enum works w/o a hitch.
The std::is_class<> trait is working fine, and the compiler is pretty much telling you what the problem is:
test.cpp:14:17: note: no known conversion for argument 1 from Foo* const to const Foo*&
You are invoking your function template this way:
xxxU_push<Foo *>(pFoo);
Which means that U will be Foo*. Now the function signature:
template<typename U>
void xxxU_push (const U& value)
Is equivalent to this:
template<typename U>
void xxxU_push (U const& value)
And after replacing Foo* for U you get this:
void xxxU_push (Foo* const& value)
Therefore, value is a constant reference to a pointer to a Foo. Inside the function, you instantiate your class template this way:
xxxU_Impl<U>::xxxU_push (value);
Which is, when substituting Foo* for U again:
xxxU_Impl<Foo*>::xxxU_push (value);
Now your class template specialization is defined this way:
template<typename U>
struct xxxU_Impl<U *, typename std::enable_if<std::is_class<U>::value>::type>
{
static void xxxU_push (const U *& value) { }
};
If you are instantiating it with Foo* as a template argument, U will be deduced to be Foo, which is a class type. Therefore, your class template gets instantiated without failures (not sure this is what you want, but this is definitely what happens), and in particular the xxxU_push() function gets instantiated this way:
static void xxxU_push (const Foo *& value) { }
Which is equivalent to this:
static void xxxU_push (Foo const*& value) { }
Can you see the difference? On the calling site you have a constant reference to a non-constant pointer, here you have a non-constant reference to a constant pointer! These two types are different, and the compiler complains that it cannot convert the argument.
You could fix your error, for instance, by changing the signature of xxxU_push() as follows:
static void xxxU_push (U * const& value) { }
// ^^^^^^^^^^
After this change, you can see the whole thing compiling here.
UPDATE:
As a follow-up from the comments, it turns out you necessarily want the static member function xxxU_push() to accept a pointer to const:
static void xxxU_push (Foo const*& value) { }
In this case, you will have to make a decision: you cannot pass a Foo* to a function which accepts a non-constant reference to a const pointer. You can, however, drop the reference:
static void xxxU_push (Foo const* value) { }
This is a first possibility to make your program compile. The second possibility is to change the call site so that it provides a pointer to const:
int main () {
Foo * pFoo = new Foo;
Foo const* pConstFoo = pFoo;
xxxU_Impl<Foo*>::xxxU_push(pConstFoo);
// ^^^^^^^^^
}
Related
Is it possible to safely cast between two function pointer in C++, given that the arguments as polymorphicly equivalent i.e. (example only)
class Base {}
class A : Base {}
class B : Base {}
class C : Base {}
template<typename T, typename U>
using FPTR = void (*)(const T&, const U&);
using index = std::pair<std:type_info, std::type_info>;
std::unordered_map<index, FPTR<Base, Base>> func_map;
template<typename T, typename U>
register(FPTR<T,U> fptr) {
// assert T and U are subclasses of Base
func_map[index(typeid(T), typeid(U))] = fptr;
}
void call(const Base& first, const Base& second) {
auto it = func_map.find(index(typeid(first), typeid(second)));
if (it != func_map.end()) {
(*it)(first, second)
}
}
void func1(const A&, const C&) {}
// call these
register<A,C>(func1);
register<B,B>([](const B&, const B&) -> void {});
so when invoking call, it would resolve the function to call based on the registered typeids, and the called function would expect the explicit type, effectively casting from the base type.
My thinking is this is going to cause an error at run time because the cast wron't occur correctly. I've considered using a lambda function to wrap fptr, but that would result in an extra indirect call, is there a way to avoid this while correctly performing the cast, note I can't cast in call, because I can only get the typeid/type_info and can't use that with the cast functions.
You can do it with an extra direct call, if that's not a problem (the target call might even be in-lineable in the wrapper, depending on your compiler and how the translation units are set up).
Something like:
struct Base {}
// ...
template <typename T, typename U>
using FPTR = void (*)(const T&, const U&);
template <typename T, typename U, FPTR<T,U> fptr>
void WrapFPTR(const Base &a, const Base &b)
{
fptr(static_cast<const T&>(a), static_cast<const U&>(b));
}
allows you to store WrapFPTR<T,U,foo> which is an FPTR<Base,Base> at every site where you register a given function foo.
If you really need an arbitrary function pointer, you'd need to store a polymorphic closure object with a pointer to that function's concrete type instead.
Current C++ contains no elaborate notion of co(ntra)variance. Can you go with static mapping instead?
#include <iostream>
class Base {};
class A : Base {};
class B : Base {};
class C : Base {};
template<typename T, typename U> using FPTR = void (*)(const T&, const U&);
// instead of allocating a run-time map, create a map on compiler's heap at compile-time
template<typename U, typename V> static FPTR<U const &, V const &> funcMap;
void nyan(A const &, A const &) { std::cout << "Nyan" << std::endl; }
void meow(B const &, B const &) { std::cout << "Meow" << std::endl; }
int main() {
funcMap<A, A> = nyan;
funcMap<B, B> = meow;
funcMap<A, A>(A{}, A{});
}
I am trying to write a Bheap in templates and the insert function involving a generic comparison function. What is the usual way to do this? I know how to use function pointer in C. But Is there any typical C++ way to do that?
Someone told the first one, which class F could represent anything any function. But I want this function to be a comparison function which like f(T,T). While the second guy say something about the functors
template <class T, class F>class Bheap
{
public:
Bheap<T>(int allocateSize);
void insert(T value, F f);
void getMax();
private:
int sizeUsed;
int allocateSize;
vector<T> myBheap;
};
You should implement your class and the insert function, assuming whatever is passed is correct in terms of the number of arguments. If the number of arguments is not 2, the compiler will let you know.
This is the desired effect in these cases. Let the compiler detect that the function is not valid, and thus the user has to change the function to the correct requirements.
A demonstration using your code would be this:
#include <vector>
template <class T, class F>
class Bheap
{
public:
Bheap(int allocateSize) {}
void insert(T value, F f)
{
f(value, value);
}
void getMax();
private:
int sizeUsed;
int allocateSize;
std::vector<T> myBheap;
};
void SomeFunction(int, int)
{}
int main()
{
typedef void (*fn)(int, int);
Bheap<int, fn> b(10);
b.insert(10, SomeFunction);
}
You will see that this compiles and links correctly (I used a function pointer, but a functor with an overloaded operator() would also suffice).
Now if the user's function is changed to one that takes 1 argument, we get a different scenario:
#include <vector>
template <class T, class F>
class Bheap
{
public:
Bheap(int allocateSize) {}
void insert(T value, F f)
{
f(value, value);
}
void getMax();
private:
int sizeUsed;
int allocateSize;
std::vector<T> myBheap;
};
void SomeFunction(int)
{}
int main()
{
typedef void (*fn)(int);
Bheap<int, fn> b(10);
b.insert(10, SomeFunction);
}
The invalid function will make your class fail to compile. Since your template requires a 2 argument function, passing a 1 argument function via pointer causes the error (which you can see here: http://ideone.com/rT7RRa)
For function objects, here is an example of successful compilation:
http://ideone.com/yvWD5o
For unsuccessful compilation:
http://ideone.com/yjeAWB
A functor is a struct providing one or more overloads of operator (), which makes it a choice if you have several comparisons:
// Having a struct X { K key, V value };
struct Less {
template <typename K, typename V>
operator bool () (const X<K, V>& a, const X<K, V>& b> const {
return a.key < b.key;
}
template <typename K, typename V>
operator bool () (const X<K, V>& a, const K& b> const {
return a.key < b;
}
template <typename K, typename V>
operator bool () (const K& a, const X<K, V>& b> const {
return a < b.key;
}
};
I have a method that takes an object as parameter
void fun(const Obj& obj)
Obj can be defined in two different ways:
struct Obj
{
Type x;
};
and
struct Obj
{
Type x[42];
};
I cannot modify the definitions of Obj (i.e. I can't rename the classes). Also, I can't modify the signature of fun and I'd rather not use preprocessor directives inside of fun. Is there a way to use metaprogramming to make this compile and work regardless of which definition of Obj is included:
void fun(const Obj& obj)
{
impl(obj); // executes some code if obj.x is an object
// executes some other code if obj.x is an array
}
? Is there a way to do it without C++11 features?
You could pick a specialization of a template based on decltype(obj.x):
template<typename T>
void impl(const Obj&);
template<>
void impl<Type>(const Obj&) {}
template<>
void imp<Type[42]>(const Obj&) {}
void fun(const Obj& obj)
{
impl<decltype(obj.x)>(obj);
}
Possible C++03 way is a member detector trait class that checks for existence of Type Obj::x. This time, template parameter of impl would be bool so you can simply pass the result of the check:
template<typename C>
struct has_Type_x {
template<typename U, U>
struct Check;
typedef char(&yes)[1];
typedef char(&no)[2];
template<typename> static no test(...);
template<typename U> static yes test(Check<Type U::*, &U::x>*);
static const bool value = sizeof(test<C>(0)) == sizeof(yes);
};
template<bool> void impl(const Obj&);
template<>
void impl<true>(const Obj&) {}
template<>
void impl<false>(const Obj&) {
std::cout << "arr";
}
void fun(const Obj& obj)
{
impl< has_int_x<Obj>::value >(obj);
}
This can be done by a second call to an implementation function fun_impl that also takes obj.x as an argument. This function specializes to scalars or arrays by two overloads, the latter accepting a reference to an array, so maintaining the array size as well:
template <typename Obj, typename T>
void fun_impl(const Obj& obj, const T& x) {}
template <typename Obj, typename T, size_t N>
void fun_impl(const Obj& obj, const T (&x)[N]) {}
template <typename Obj>
void fun(const Obj& obj)
{
fun_impl(obj, obj.x);
}
This works in C++03 and does not require any traits features or SFINAE. See also live example, where the remaining parts use C++11 for convenience.
If obj only contains x, you can drop it as an argument from fun_impl. I left it here for the more general case where obj might have other members as well.
Note that fun itself is given as a template here; I guess this is what you need to do anyway since you are dealing with different definitions of Obj.
My suggestion is to use function overloading. You don't need metaprogramming/templates in your case:
void fun(const Obj& obj)
{
impl(obj.x);
}
void impl(const Type& x){...}
void impl(Type x[]){...}
If Obj::x is declared as Type x then the first impl() version will be called. And similarly in another case the second impl() version will be called.
I am making a function template:
template <typename T>
void foo (T arg1) {}
But I want to make sure T is deferencable to type Foo, so arg1 needs to be either:
Foo * //This case T = Foo*
Or
Any type X which implements `*` operator which returns a Foo/Foo&/Foo&&
So I need something like:
template <typename T>
void foo(T arg1, std::enable_if<std::is_same<typeid(*arg1), typeid(Foo)>::value> * = 0) {}
But this does not compile and complains:
typecheck.cpp:6:54: error: use of parameter âarg1â outside function body
void foo(T arg1, std::enable_if<std::is_same<typeid(*arg1), typeid(Foo)>::value> * = 0) {}
^
How can I achieve this?
You should prefer is_convertible instead of is_same to catch sub classes of Foo, the enable_if in the template argument list instead of the function arguments or return type is also easier to read.
template <typename T, typename = typename std::enable_if<std::is_convertible<decltype( *std::declval<T>() ), Foo>::value>::type >
void foo(T arg1);
less garbage in c++14 :
template <typename T, typename = std::enable_if_t<std::is_convertible<decltype( *std::declval<T>() ), Foo>::value> >
void foo(T arg1);
You want decltype, not typeid. You use typeid to get run-time type information, whereas decltype will give you the type of an expression at compile-time.
std::is_same<decltype(*arg1), Foo>::value
Note, if you don't need a call with a type that doesn't point at a Foo to fall back to a different overload, then you might prefer to use static_assert instead of std::enable_if:
template <typename T>
void foo(T arg1) {
static_assert(std::is_same<decltype(*arg1), Foo>::value, "Performing indirection with an object of type T must give a Foo");
// ...
}
A template is way too complicated:
void foo(Foo&);
void foo(const Foo&);
void foo(Foo*);
void foo(const Foo*);
and dispatch accordingly.
#include <iostream>
struct Foo {};
struct Any {
operator Foo () const { return Foo(); }
};
void foo(const Foo&) {
std::cout << "Hello Foo\n";
}
int main() {
Any a;
foo(a);
}
I'm writing some classes that use boost::fusion::map. Bellow you find a simplified code:
template <typename ObjDef>
struct Object
{
typedef
typename
boost::fusion::result_of::as_map<valid_list_of_fusion_pairs>::type map_type;
map_type map;
Object()
: map()
{}
Object(Object const & other)
: map(other.map)
{}
Object & operator=(Object const & other)
{
map = other.map;
return *this;
}
// non-const version
template <typename FieldId>
typename
boost::fusion::result_of::at_key<map_type, FieldId>::type get()
{
return boost::fusion::at_key<FieldId>(map);
}
// const version
template <typename FieldId>
typename
boost::fusion::result_of::at_key<map_type const, FieldId>::type get() const
{
return boost::fusion::at_key<FieldId>(map);
}
};
and another class:
template <typename Obj, typename FieldId>
class Field
{
private:
Obj &obj_m;
public:
// type returned by \c operator()
typedef
typename
boost::fusion::result_of::at_key<typename Obj::map_type, FieldId>::type return_type;
// type returned by \c operator() const
typedef
typename
boost::fusion::result_of::at_key<typename Obj::map_type const, FieldId>::type return_type_const;
Field(Obj &obj)
: obj_m(obj)
{ }
virtual ~Field()
{ }
return_type operator()()
{
return obj_m.template get<FieldId>();
}
return_type_const operator()() const
{
/*
* PROBLEM!
*/
Obj const & obj_const = obj_m;
return obj_const.template get<FieldId>();
}
};
Look for "PROBLEM!" in the comments in the above code. In that method, the compiler ignores the const qualifier of the method and calls the non-const version of obj_m.get() allowing to do something like:
obj_m.template get<FieldId>() = 10;
which is not correct since this method is const! Then, to force the compiler to call the const version, a const reference to obj_m is declared. Now the sentence
obj_const.template get<FieldId>() = 0;
produces a compilation error. So far this is not a problem for the current method,but it is not convenient for const correctness and it is definitively undesired
any idea why is this happening?
thanks!