I have a function:
int foo(void * ptr)
{
// ...
}
Can I syntactically (not with compiler warnings, etc.) in C++11/14 disable passing there pointers other than void * itself?
For example, now it can be called like:
foo(new int(42));
I need to disable this.
I suppose there are many other ways of doing it.
Using template functions is simple (it works with C++98 too)
template <typename X>
int foo (X * ptr);
int foo (void * ptr)
{ return 1; }
int main()
{
int i;
void * vp = &i;
foo(vp); // OK
foo(&i); // linker error
return 0;
}
As pointed by frymode, the preceding solution give a linker error, not a compiler error, and it's better to get a compiler error.
Using delete (from C++11) we can get a compiler error by using this instead:
template <typename X>
int foo (X ptr) = delete;
Hope this helps.
You can make use of pedantic pointer idiom. Your code should look as bellow. It makes use of the fact that there is no implicit conversions at the higher that one level of indirection:
[live]
int foo_impl(void * ptr, void **)
{
return 0;
}
template <typename T>
void foo(T* t)
{
foo_impl(t, &t);
}
int main()
{
void* pv;
foo(pv);
//foo(new int(2)); // error: error: invalid conversion from 'int**' to 'void**'
}
If you want exact type match you can use std::enable_if with std::is_same
#include <iostream>
#include <type_traits>
template <typename T,
typename = typename std::enable_if_t<std::is_same<T, void*>::value>>
int foo(T value)
{
return 5;
}
int main()
{
// return foo(new int(42)); // error: no matching function for call to 'foo(int*)'
return foo((void*)(new int(42)));
}
You can turn the function to a template one, then use a static_assert and std::is_void from type_traits:
template<typename T>
int foo(T *ptr) {
static_assert(std::is_void<T>::value, "!");
// ....
}
Otherwise, you can use a std::enable_if_t on the return type:
template<typename T>
std::enable_if_t<std::is_void<T>::value, int>
foo(T *ptr) {
// ....
return 0;
}
And so on, other interesting solutions have already been proposed by other users with their answers.
Here is a minimal, working example:
#include<type_traits>
template<typename T>
int foo(T *ptr) {
static_assert(std::is_void<T>::value, "!");
// ....
return 0;
}
int main() {
int i = 42;
void *p = &i;
foo(p);
// foo(&i); // compile error
}
The idiomatic way would be to create a new type to represent void* to avoid the problem you are describing. Many advocates of good C++ practices suggest creating types to avoid any doubt about what should be passed in and also avoid the compiler letting you.
class MyVoid
{
//... implement in a way that makes your life easy to do whatever you are trying to do with your void* stuff
};
int foo(MyVoid ptr)
{
// ...
}
You don't need C++11 to ensure a compile-time error:
template<class> struct check_void;
template<> struct check_void<void> { typedef void type; };
template<class T> typename check_void<T>::type *foo(T *ptr) { return ptr; }
int main()
{
foo(static_cast<void *>(0)); // success
foo(static_cast<int *>(0)); // failure
}
Related
I was wondering if it was possible to deduce the return type, and parameters from a function type define.
I was hoping to do something similar:
template<class T>
struct _function_wrapper_t
{
[return of T] call([Args of T]....)
{
return (T)m_pfnFunc(Args);
}
void* m_pfnFunc;
};
int MultiplyTwoNumbers(int nNum, int nNum2)
{
return nNum * nNum2;
}
int MultiplyThreeNumbers(int nNum, int nNum2, int* pnNum3)
{
return nNum * nNum2 * *pnNum3;
}
int main()
{
_function_wrapper_t<decltype(&MultiplyTwoNumbers)> two(&MultiplyTwoNumbers);
_function_wrapper_t<decltype(&MultiplyThreeNumbers)> three(&MultiplyThreeNumbers);
auto ret1 = two.call(1, 2);
auto ret2 = three.call(4, 5, 8);
}
However I'm not sure if its possible to discern the return type and function arguments from a type of function pointer.
if you did say
typedef void*(__cdecl* fnOurFunc_t)(const char*, int, float**);
The compiler knows to use that as the type in the future, does the same apply further to templates? This is needed for a VERY specific use case.
Thanks in advance!
The simple solution is to let the compiler deduce return type and let the caller pass the right types (and fail to compile when they don't):
template<class T>
struct _function_wrapper_t
{
template <typename ...U>
auto call(U&&... t)
{
return m_pfnFunc(std::forward<U>(t)...);
}
T m_pfnFunc;
};
If you do not like that you can use partial specialization:
template<class T>
struct _function_wrapper_t;
template <typename R,typename...Args>
struct _function_wrapper_t<R(*)(Args...)>
{
R call(Args...args)
{
return m_pfnFunc(args...);
}
using f_type = R(*)(Args...);
f_type m_pfnFunc;
};
Live Demo
PS: perfect forwarding is also possible in the latter case but it requires some boilerplate that I left out for the sake of brevity.
Check the std::function implementation. It seems it does what you need:
#include <functional>
int MultiplyTwoNumbers(int nNum, int nNum2)
{
return nNum * nNum2;
}
int MultiplyThreeNumbers(int nNum, int nNum2, int pnNum3)
{
return nNum * nNum2 * pnNum3;
}
int main()
{
std::function<decltype(MultiplyTwoNumbers)> two = &MultiplyTwoNumbers;
std::function<decltype(MultiplyThreeNumbers)> three = &MultiplyThreeNumbers;
auto ret1 = two(1, 2);
auto ret2 = three(4, 5, 8);
}
Consider this function:
void func(int* a = nullptr)
{
if (a)
*a = 1;
}
I can then call function without the parameter, as it has the default value (func()) or I can obtain a value via the parameter (func(somePtr)).
Now I was trying to figure out either the same functionality is possible to accomplish without method overloading with references. The closest thing I got was utilizing an universal reference, but in this case I am bound to using template types and in my case my type is strict. Is there a way to translate this bare pointer functionality to references functionality?
One way of doing this I came up with is:
void func(int& a)
{
a = 5;
}
void func()
{
int dummy;
fund(dummy);
}
I am aiming for something like this (wont work):
template<typename T>
void func(T&& a = int())
{
a = 1;
}
Overloading is the most natural way, e.g.
void func(int& a) { a = 1; /* assume some other complex logic here */ }
void func(int&& a = int()) { func(a); }
It is possible to make the SFINAE version work, although I'm sure aesthetic views will differ:
#include <type_traits>
template<typename T, typename U>
using EnableIfSame = std::enable_if_t<std::is_same_v<std::remove_reference_t<T>, U>>;
template<typename T = int, typename = EnableIfSame<T, int>>
void func(T&& a = int())
{
a = 1;
}
If you don't have C++17 then is_same_v<Z> would need to be replaced with is_same<Z>::value, and if not C++14 then enable_if_t<Z> with typename enable_if<Z>::type .
I'm not sure I could figure out your problem. Maybe this method answers your question.
void *p;
template <typename T>
void func(T def, T& t = *(T *)p)
{
if (&t != p)
t = def;
}
int main()
{
int a;
func(1);
func(1, a);
}
So, I have a template class, which must call a callback function at some time. That callback function takes const T template as an argument.
I pass that function's pointer to a template class Boom<void*>. However, the const T argument of that callback is interpreted as just T.
But this is the case only with void*.
The code:
//main.cpp
void kolbek(const void* val)
{
if(val)
printf("Value is: %d\n", *((int*)val));
else
printf("Value ptr = NULL\n");
}
int main()
{
Boom<void*> bomba;
bomba.setCallback(kolbek); //error!
int* nuint = new int(5);
bomba.callCallback((void*)nuint);
delete nuint;
return 0;
}
//boom.h
template<typename T>
class Boom
{
private:
void (*someCallback)(const T) = nullptr;
public:
Boom(){ }
~Boom(){ }
void setCallback(void (*callbk)(const T));
void callCallback(const T val);
};
//boom.cpp
template<typename T>
void Boom<T>::setCallback(void (*callbk)(const T))
{
this->someCallback = callbk;
}
template<typename T>
void Boom<T>::callCallback(const T val)
{
if(someCallback)
(*someCallback)(val);
else
printf("Bad! Callback's NULL!\n");
}
template class Boom<int>;
template class Boom<void*>;
And when trying to compile this, an error is thrown:
error: invalid conversion from 'void (*)(const void*)' to 'void (*)(void*)' [-fpermissive]
error: initializing argument 1 of 'void Boom<T>::setCallback(void (*)(T)) [with T = void*]' [-fpermissive]
How to fix it? Seems like only void* pointers are wrongly interpreted.
Your problem comes from confusing two different consts. This is why it can be helpful to write T const instead of const T - it makes textual substitution not lie to you.
Boom's callback takes a T const which in your instatiation is void* const (not const void*!!): it's a const pointer to non-const void. kolbek's argument takes a void const* - a pointer to const void. Those aren't the same type. You can do a qualification conversion from the former to the latter, but not the other way around (you'd be casting away const!). This is your compiler error.
The simplest solution is not not have Boom add const. It's unnecessary. Use the T as provided and use Boom<const void*>.
In the case mentioned in comment you could create helper struct to make your template dereferenced parameter const:
template<class T>
struct ptr_constantizer {
using type = const T;
};
template<class T>
struct ptr_constantizer<T*> {
using type = const T*;
};
template<typename T>
class Boom
{
private:
void (*someCallback)(typename ptr_constantizer<T>::type) = nullptr;
public:
Boom(){ }
~Boom(){ }
void setCallback(void (*callbk)(typename ptr_constantizer<T>::type)) { }
void callCallback(const T val) { }
};
void foo(const void *ptr) {
}
void fooi(const int non_ptr) {
}
int main() {
Boom<void *> b;
Boom<int> bi;
b.setCallback(&foo);
bi.setCallback(&fooi);
}
The code assumes you are using c++11 as you used nullptr in your example...
How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);
I have a class A:
template <typename T, int I> struct A {};
and a class B. I would like object's of type B to implicitly convert to A when given as function arguments. B looks like this:
template <typename T>
struct B {
operator A<T,0> &() const { return *new A<T,0>(); }
};
However, my test (below) fails with GCC 4.5, giving the error: no matching function for call to 'test(B&)' Where am I going wrong here? Do other compilers also reject this?
template <typename T, int I>
void test(A<T,I> &a) { delete &a; }
int main(int argc, char *argv[])
{
B<int> b;
test(b);
return 0;
}
p.s. I've now put my own solution in an answer below.
Unrelated to your problem but return *new A<T,0>(); is wrong since it leaks memoryinvites a memory leak. You should not use new here. return A<T, 0>(); and removing the reference from the return type works just fine and does not leak memory.
If you want an implicit conversion from B to A you would need either:
A cast operator on B:
operator A<T,0>();
or an A constructor which takes a B reference:
A( const B& other );
or for B to derive from A. What you have declared:
operator A<T,0> &() const;
looks a bit like an ill-declared address-of overload.
However, since test() takes a reference (and non-const at that), the casting operator option won't work.
This is what I've tested:
template <typename T, int I> struct A {};
template <typename T>
struct B {
//operator A<T,0> &() const { return *new A<T,0>(); }
template< int I >
operator A<T, I> () const { return A< T, 0 >(); }
};
template <typename T, int I>
void test(A<T,I> &) { }
int f()
{
B<int> b;
A<int, 0> a( b );
test(a); // <-- Success
test(b); // <-- Failure, "could not deduce template argument"
return 0;
}
Conversion to A by initialising a local variable works fine.
Are you sure you actually want such an implicit conversion here? It sounds like a perfect way to confuse yourself or another maintainer, or worse, call a function using the wrong argument because the implicit conversion allows it. Instead, consider a make_A template like std::make_pair to explicitly show your intention at the call site.
Providing an overload of test like the following will enable to write
test(b) as in the question.
For example:
template <typename T>
void test(B<T> const &b) {
test( static_cast< A<T,0>& >( b ) );
}
test(b); // caller
If such overload isn't allowed but you are allowed to modify B's
definition, how about providing member function which returns A
like the following, instead of conversion function?
template <typename T>
struct B {
A<T,0> &to_A() const { return *new A<T,0>(); }
};
test( b.to_A() );
If you aren't allowed to modify B's definition, the above to_A will be
a free function like the following instead of member function:
template <typename T>
A<T,0> &to_A(B<T> const &b) {
return static_cast< A<T,0>& >( b );
}
test( to_A( b ) );
Hope this helps
This fails in VC++ too. To make it work, add this method:
template <typename T>
void test(B<T> &b)
{
test( static_cast< A<T,0>& > (b) );
}
This will take an actual B, explicitly do the conversion (via static_cast), and then call test using the A we just made.
I get errors when I run it though. I hope this is just example code, and you're not doing delete &a in your actual code. RobH gave a better conversion operator for you, and avoids the pointer messiness.
I've settled on using the pass by value conversion operator suggested by Konrad; the explicit template function call of Let_Me_Be; and I sprinkled a little bit of C++0x magic on top: an rvalue reference on the parameter to test. (Or, should that be C++ 2011 now?)
template <typename T, int I> struct A { int x; };
template <typename T>
struct B {
operator A<T,0> () const { return A<T,0>(); }
};
template <typename T, int I>
void test(A<T,I> &&a) { a.x=7; printf("%d\n", x); }
int main(int argc, char *argv[])
{
B<int> b;
test<int,0>(b);
return 0;
}