I have a delima. I'm using wrapper classes for native types, however, when using the wrapper types as function arguments, the implicit conversion for char pointer to bool keeps causing the compiler to issue an ambiguous function call error:
class VBool
{
public:
VBool(bool b):value(b){}
template<class T>
VBool(T)=delete;
private:
bool value;
};
class VString
{
public:
VString(const char* str):value(str){}
private:
std::string value;
};
void processVType(VBool vb){}
void processVType(VString vs){}
int main()
{
processVType(""); // rejected as ambiguous by compiler.
return 0;
}
Now the compiler allows:
VBool b = true;
And correctly rejects:
VBool b = "string";
But how do I get the compiler to correctly identify the intended function version to be called?
Note: I'm using VCC compiler with language standard for C++17 enabled.
Add another function with proper parameter.
inline void processVType(const char* vs) { processVType(VString(vs)); }
Just out of curiosity, why are you trying to implement something like this?
Related
I have the following class (and some specilization for certain types):
template <typename Type>
class SimpleOptional {
public:
SimpleOptional(Type content) : value_(true), content_(content) {}
// obviously simplified...
private:
bool value_;
Type content_;
};
which is part of a foreign function interface. The function must be declared with extern "C" like this:
extern "C" SimpleOptional<char*> b(char *a) {
return a + 4; // implicitly constructing SimpleOptional<char*>
}
This code works fine with GCC and Clang on macOS and Linux.
However MSVC does not like it and complains that a function with C linkage may not return a C++ class.
So far I came up with this (where MS_O will only be defined for MSVC):
template <typename Type>
class SimpleOptional {
public:
SimpleOptional(Type content) : value_(true), content_(content) {}
using ContentType = Type;
private:
bool value_;
Type content_;
};
#define MS_O(type) struct { bool b; type::ContentType v; }
extern "C" MS_O(SimpleOptional<char*>) b(char *a) {
return a + 4;
}
Although that fixes the return type issue, I still have no implicit construction and MSVC complains about not being able to convert char* to the return type.
Is there any kind of workaround that doesn't cost me C++ implicit construction?
I'm implementing a class that performs type erasure for small objects and have encountered a segmentation fault which I do not understand.
The following program:
#include <iostream>
#include <type_traits>
struct small_object
{
public:
template<class T>
small_object(const T& value)
{
new(&storage_) concrete<T>(value);
}
~small_object()
{
get_abstract().~abstract();
}
void print() const
{
// XXX crash here
get_abstract().print();
}
private:
struct abstract
{
virtual ~abstract(){}
virtual void print() const = 0;
};
template<class T>
struct concrete
{
concrete(const T& value) : value_(value) {}
void print() const
{
std::cout << value_ << std::endl;
}
T value_;
};
abstract& get_abstract()
{
return *reinterpret_cast<abstract*>(&storage_);
}
const abstract& get_abstract() const
{
return *reinterpret_cast<const abstract*>(&storage_);
}
typename std::aligned_storage<4 * sizeof(void*)> storage_;
};
int main()
{
small_object object(13);
// XXX i expect this line to print '13' to the terminal but it crashes
object.print();
return 0;
}
Crashes at the lines indicated by XXX.
I believe the issue is that the virtual call to .print() is not being dynamically dispatched correctly, but I don't understand why.
Can anyone tell what am I missing?
You didn't derive concrete<T> from abstract, so no vtable is being created when you construct the object using placement new. Therefore, when you try to invoke the virtual function, it will fail; concrete<T> and abstract are actually completely unrelated types in this example.
I would recommend using the override keyword if you're using C++11 or newer to allow the compiler to generate an error in cases like this.
std::aligned_storage<4 * sizeof(void*)> storage_;
This creates storage of one byte.
The template argument does not set the size of the declared object, but rather the size of an object that can be allocated in a suitably-sized array of this type. Hence, you need
std::aligned_storage<4 * sizeof(void*)> storage_[4 * sizeof(void*)];
GCC 6.2.0 warns you about this:
warning: placement new constructing an object of type ‘small_object::concrete<int>’ and size ‘16’ in a region of type ‘std::aligned_storage<32ul>’ and size ‘1’ [-Wplacement-new=]
(You still need to derive concrete from abstract).
Is is possible to create a class Wrapper such that
void f(void *) {}
Wrapper w;
f(w);
compiles, but
Wrapper w;
if (w) {}
doesn't compile? Or detect the difference at runtime?
Background: A win32 HANDLE is a typedef for void *. Win32 doesn't use NULL but instead ((HANDLE)(-1)) as an error value, so any code implicitly casting a HANDLE to bool is almost certainly testing the wrong thing. I have a class wrapping a HANDLE, and if possible I would like to remove this opportunity for errors when using the wrapper class.
In C++11 it is possible by using deleted functions. For instance:
struct Wrapper
{
operator void* () { }
operator bool () = delete;
};
void foo(void*) { }
int main()
{
Wrapper w;
foo(w); // OK
if (w) // ERROR!
{
// ...
}
}
If you are working with a compiler that does not support C++11, you can achieve the same result by declaring the bool conversion operator private:
struct Wrapper
{
operator void* () { }
private:
operator bool () { };
};
This works because accessibility of a function is verified only at the very last step of overload resolution.
Well, here's a version that works, but bear in mind that this is a terrible idea to have in production code:
struct Wrapper {
void *_value;
Wrapper() : _value(NULL) {
};
template<typename T>
Wrapper(T *value) : _value(value) {
};
void *operator &() {
return _value;
};
};
void func(void *value) {
printf("%p", value);
}
int main()
{
Wrapper w = (void *) 0xFFAABB;
if (w) // error, 'No viable conversion from 'Wrapper' to 'bool'
{
func(&w); // 0xffaabb
}
}
You cannot pass the wrapper directly, but passing the address of the wrapper will convert it to the address of the value.
Be very careful if you are trying to use this with external template functions, as they may not operate correctly.
I've a problem on this code:
template <typename T>
void dosth(T& value,const T& default_value)
{
if (condition)
value = 10;
else
value = default_value;
}
When I call that with
enum {
SITUATION1,
STIUATION2
};
int k;
dosth(k,SITUATION1);
the compiler (g++ 4.5) says
no matching function for call to 'dosth(int&,)'
Why doesn't the compiler automatically cast the enum into an int?
Your problem is due to the fact that the template cannot be instantiated from the function arguments that you supply. No implicit conversion to int occurs, because there's no function to call at all.
If you cast instead of attempting to rely on implicit conversion, your program will work:
dosth(k, static_cast<int>(SITUATION1));
Or, if you provide the function template's arguments explicitly, then the function argument will be converted implicitly as you expect, and your program will work:
dosth<int>(k, SITUATION1);
Would this be better for enums?
class Situations
{
private:
const int value;
Situations(int value) : value(value) {};
public:
static const Situations SITUATION1() { return 1; }
static const Situations SITUATION2() { return 2; }
int AsInt() const { return value; }
};
Will enable type safety. Then use it to create a type safte template.
i.e. Value for pass or fail.
I need to instantiate a free template function (FTF) within a template class (TC). The FTF takes as a template parameter one of the template parameters of the TC. The TC also holds generic pointers to these FTF's, and these functions are called through the pointers.
The step of taking a pointer to a FTF is not enough to instantiate it, and I receive linker errors from the GCC toolchain. MSDN illustrates FTF specification as so -- however my instantion of the FTF is dependant on a template parameter of my TC, and therefore the FTF instantiation cannot be placed in free scope.
Is this possible ? I am attaching some basic generated code, the issue is in the constructor of the class test_service, where I assign the pointer of a free function into a custom container. I get a linker error telling me the free function cannot be found (uninstantiated). I know that specifying a call to the template function in the class somewhere will produce a instantiation, however I am only going to be making a call via a pointer.
#include "rpc_common.h"
#include <boost/cstdint.hpp>
namespace rubble { namespace rpc {
struct test_service_dummy_tag{};
template<typename T>
class test_service_skel
{
public:
bool Init() {}
bool TearDown() {}
bool test_one(TestRequest,TestResponse){};
private:
};
template<typename T_IMPL>
bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
{
return 0;
}
template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
class test_service
{
public:
test_service()
{
// uncomment the following two lines and a instantiation will occur.
// ClientRequest cr;
//test_service_test_one<T_IMPL>(m_impl,cr);
m_dispatch_table.SetEntry( Oid("test_one",0),(void *) & test_service_test_one<T_IMPL>);
}
bool Init() { return m_impl.Init(); };
bool TearDown() { return m_impl.TearDown(); };
private:
T_IMPL m_impl;
OidContainer<Oid,void *> m_dispatch_table;
};
} }
EDIT: self-contained minimal version
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T>
bool test_function()
{
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = (void *) & test_function<T>;
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
There is no problem iff you don't use a void*, i.e.: http://www.ideone.com/eRgUG
However, if you insist on storing the pointer in a void*, then you need to take the address using a specific function pointer first and then cast - e.g.
bool (*temp)() = &test_function<T>;
dispatch = reinterpret_cast<void*>(temp); // YUCK
This gives the compiler enough context to generate the address for you.
Ahh - just saw DeadMG's answer, the function to generate the void* is neater...
Your self-contained example wouldn't compile for me with a strange error about overloaded functions, when there is no overloading going on, with MSVC. I did, however, manage to work around it.
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T> void* to_void_pointer(T t) {
return reinterpret_cast<void*>(t);
}
template<typename T>
bool test_function()
{
return true;
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = to_void_pointer(&test_function<T>);
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
This compiles cleanly. I suspect that whatever behaviour you're seeing and I saw is a compiler error.