boost::any_cast and std::optional's - c++

I use boost::any, and have some function which retrieves such a value, but may fail, so it actually returns std::optional<boost::any> (well, for now it's std::experimental::optional). Now, without the optional, I get my typed value back using boost::any_cast(my_retrieved_any). To handle the optional case, I've written the following:
template<typename ValueType>
inline const optional<ValueType> boost_any_cast(const optional<boost::any>& operand)
{
return operand ? boost::any_cast(operand.value()) : nullopt;
}
But this doesn't compile (with Boost 1.58 and GCC 4.9.3). I get:
/file.cpp(12): error: no instance of overloaded function "boost::any_cast"
matches the argument list
argument types are: (const boost::any)
How is this possible? Why is the argument not boost::any& ? I tried setting a variable to operand.value(), then passing that to the any_cast - but that didn't seem to help either:
template<typename ValueType>
inline const optional<ValueType> boost_any_cast(const optional<boost::any>& operand)
{
if (operand) {
boost::any x(operand.value());
return boost::any_cast(x);
}
return nullopt;
}
This gets me:
/file.cpp(13): error: no instance of overloaded function "boost::any_cast"
matches the argument list
argument types are: (boost::any)
There must be something I'm not taking into account regarding boost::any's... what is it? And how can I fix this "casting" operation?

The boost::any_cast requires a template argument;
template<typename T> T any_cast(const any &);
From you code snippet, you probably need;
boost::any_cast<ValueType>(operand.value())

Related

Cannot convert from const_Ty2* to ValueType*

template <typename ValueType> ValueType* RadixTree<ValueType>::search(std::string key) const {
typename std::map<std::string, ValueType>::const_iterator it = radixTree.find(key);
if (it == radixTree.end())
return nullptr;
return &(it->second);
}
Hello! above is my code which is a placeholder for my radixTree implementation. I don't understand why I need the typename before the std::map on the second line, and why &(it->second) would end up returning a const_Ty2*. I thought that in this case, const_Ty2 and ValueType were equivalent. The variable radixTree is currently a Map, and although I want to replace this with my radixTree implementation, I also want to understand the problem I'm getting right now. Any help would be greatly appreciated. Thank you!
Follow up:
I'm also getting an issue w/ this method
template <typename ValueType> void RadixTree<ValueType>::insert(std::string key, const ValueType& value) {
radixTree.insert(key, value);
}
and radixTree is declared as
std::map<std::string,ValueType> radixTree;
This method gives me a really long error that I can't quite understand.
std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string,ValueType>>>> std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>::insert(std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string,ValueType>>>>,std::pair<const std::string,ValueType> &&)': cannot convert argument 1 from 'std::string' to 'std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string,ValueType>>>>
Can someone help me w/ this too? Thank you again!
Your function is const and you're correctly using a const_iterator. This means that it->second is also const. When you do &it->second that becomes a const pointer which cannot be implicitly converted to a non-const pointer (such a conversion discards the const qualifier).
It's unclear why you want a non-const pointer to an internal value. I have to presume it's an error. You should change the return type to const ValueType*.
Regarding the edit you just made to your question:
radixTree.insert(key, value);
The message is telling you that the function arguments are wrong. Check the documentation for the insert function. You'll find that it requires a value_type which is a std::pair<const Key, T>. The useful part of the error is here:
cannot convert argument 1 from 'std::string' to 'std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string,ValueType>>>>
There it is trying to match a call that has two arguments, which the overload resolution is trying to resolve it to insert(const_iterator hint, const value_type &value). That should tell you something is wrong.
Try this:
radixTree.insert(std::make_pair(key, value));

Casting to void to avoid use of overloaded user-defined Comma operator

I am learning about templates in C++, and came across an example where casting to void is used:
template<typename T>
auto func (T const& t) -> decltype( (void)(t.size()), T::size_type() )
{
return t.size();
}
In the explanation it is written that:
The cast of the expression to void is to avoid the possibility of a user-defined comma operator overloaded for the type of the expressions.
My question(s) is/are:
How can a cast to void be used to "avoid the possibility of a user-defined comma operator overloaded for the type of the expressions"? I mean, can anyone give any example where if we don't use void then this code would give an error? For example, let's say we have a class called SomeClass which has overloaded the comma operator. Now, can this become a problem if we don't use void?
Can static_cast be used in this case instead of a C style cast? For example, something like static_cast<void>(t.size()). I am reading examples that use C++17 features, and so I wonder why the author has used a C style cast in this case.
I have read What does casting to `void` really do?, from which I get the impression that if we use (void)x then this means to suppress compiler warnings, and also means "ignore the value of x". But then I can't understand the difference between the expression x and (void)x.
Consider this pathological type:
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() { return {};}
};
It does have a size_type and it does have a size() method. However, without the cast to void, the template does not deduce the right return type, because decltype( (t.size()), typename T::size_type() ) is bool :
#include <type_traits>
template<typename T>
auto func (T const& t) -> decltype( (t.size()), typename T::size_type() )
{
return t.size();
}
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() const { return {};}
};
int main()
{
func(foo{});
}
Results in error:
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
1 error generated.
ASM generation compiler returned: 1
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
A static_cast can be used. However, as nothing is actually being cast (it is an unevaluated context), the c-style cast does not do much harm. Note how by using the cast to void the user defined operator, is bypassed and the correct return type is deduced: https://godbolt.org/z/jozx1YGWr. This is because void, whatever uses the built-in operator, whose result is of same type as whatever. You cannot override void, whatever with a user-defined operator,; there is no syntax that works.
I suppose the code is merely to illustrate this one effect, because even with the cast to void one can make up other examples that fail (eg the template does not explicitly test for t.size() actually returning T::size_type).
See also the section on "Rarely overloaded operators" here:
The comma operator, operator,. Unlike the built-in version, the overloads do not sequence their left operand before the right one. (until C++17) Because this operator may be overloaded, generic libraries use expressions such as a,void(),b instead of a,b to sequence execution of expressions of user-defined types. The boost library uses operator, in boost.assign, boost.spirit, and other libraries. The database access library SOCI also overloads operator,.

std::function as template parameter

I currently have a map<int, std::wstring>, but for flexibility, I want to be able to assign a lambda expression, returning std::wstring as value in the map.
So I created this template class:
template <typename T>
class ValueOrFunction
{
private:
std::function<T()> m_func;
public:
ValueOrFunction() : m_func(std::function<T()>()) {}
ValueOrFunction(std::function<T()> func) : m_func(func) {}
T operator()() { return m_func(); }
ValueOrFunction& operator= (const T& other)
{
m_func = [other]() -> T { return other; };
return *this;
}
};
and use it like:
typedef ValueOrFunction<std::wstring> ConfigurationValue;
std::map<int, ConfigurationValue> mymap;
mymap[123] = ConfigurationValue([]() -> std::wstring { return L"test"; });
mymap[124] = L"blablabla";
std::wcout << mymap[123]().c_str() << std::endl; // outputs "test"
std::wcout << mymap[124]().c_str() << std::endl; // outputs "blablabla"
Now, I don't want to use the constructor for wrapping the lambda, so I decided to add a second assignment operator, this time for the std::function:
ValueOrFunction& operator= (const std::function<T()>& other)
{
m_func = other;
return *this;
}
This is the point where the compiler starts complaining. The line mymap[124] = L"blablabla"; suddenly results in this error:
error C2593: 'operator = is ambiguous'
IntelliSense gives some more info:
more than one operator "=" matches these operands: function
"ValueOrFunction::operator=(const std::function &other) [with
T=std::wstring]" function "ValueOrFunction::operator=(const T
&other) [with T=std::wstring]" operand types are: ConfigurationValue =
const wchar_t
[10] c:\projects\beta\CppTest\CppTest\CppTest.cpp 37 13 CppTest
So, my question is, why isn't the compiler able to distinguish between std::function<T()> and T? And how can I fix this?
The basic problem is that std::function has a greedy implicit constructor that will attempt to convert anything, and only fail to compile in the body. So if you want to overload with it, either no conversion to the alternative can be allowed, of you need to disable stuff that can convert to the alternative from calling the std::function overload.
The easiest technique would be tag dispatching. Make an operator= that is greedy and set up for perfect forwarding, then manually dispatch to an assign method with a tag:
template<typename U>
void operator=(U&&u){
assign(std::forward<U>(u), std::is_convertible<U, std::wstring>());
}
void assign(std::wstring, std::true_type /*assign_to_string*/);
void assign(std::function<blah>, std::false_type /*assign_to_non_string*/);
basically we are doing manual overload resolution.
More advanced techniques: (probably not needed)
Another approach would be to limit the std::function = with SFINAE on the argument being invoked is valid, but that is messier.
If you have multiple different types competing with your std::function you have to sadly manually dispatch all of them. The way to fix that is to test if your type U is callable with nothing and the result convertible to T, then tag dispatch on that. Stick the non-std::function overloads in the alternative branch, and let usual more traditional overloading to occur for everything else.
There is a subtle difference in that a type convertible to both std::wstring and callable returning something convertible to T ends up being dispatched to different overloads than the original simple solution above, because the tests used are not actually mutually exclusive. For full manual emulation of C++ overloading (corrected for std::functions stupidity) you need to make that case ambiguous!
The last advanced thing to do would be to use auto and trailing return types to improve the ability of other code to detect if your = is valid. Personally, I would not do this before C++14 except under duress, unless I was writing some serious library code.
Both std::function and std::wstring have conversion operators that could take the literal wide string you are passing. In both cases the conversions are user defined and thus the conversion sequence takes the same precedence, causing the ambiguity. This is the root cause of the error.

Why is this cast ambiguous?

I have a class that I have written which does type erasure. The public interface is:
template <typename T>
value(const T &t);
value(value &&v);
template <typename T>
operator T() const;
When I create a value instance from a std::string I have no problems, everything works as expected. When I try to get the std::string back out, using static_cast<std::string>(val), where val is an instance of value that is holding a std::string, I get the following error from VS2012:
error C2440: 'static_cast' : cannot convert from 'value' to std::string'
No constructor could take the source type, or constructor overload resolution was ambiguous
If I comment out the templated cast operator and add operator std::string() const then it compiles. I figure that something between the std::string constructors and the templated cast operator have the same goodness of match. Could anyone suggest what is happening and how to fix it?
Igor explained the problem. Here's my suggested solution:
Your class is obviously only intended to store one type of object at a time, so make that explicit. Replace the conversion functions with a real function:
template <typename T>
T get() const;
Now call it like this:
std::string myString = myValue.get<std::string>( );
No ambiguity. No chance of the wrong function being called and messing everything up. And I'd argue that it is now more readable.
std::string has several constructors capable of being called with one parameter - e.g. one taking const string&, and another taking const char*. What should T resolve to, then?
From the C++ standard:
5.2.9p4 Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_cast<T>(e) if the declaration T t(e); is well-formed, for some invented temporary variable t.
In your case, the declaration std::string t(val); is ill-formed.
Following works with std::string (if you can return a reference).
static_cast<const std::string&>(val);

Implicit casting in templates and compiler coercion

I have this very simple wrapper template:
template<class T>
struct wrapper {
inline operator T () {
return v;
}
inline wrapper(T v):v(v) { }
T v;
};
Trying to use it with any non-primitive type with (for example) comparison operator relying on the template having it defined doesn't look promising:
std::string t = "test";
assert(t == t);
typedef wrapper<std::string> string_wrapper;
assert(string_wrapper(t) == string_wrapper(t));
GCC 4.4.5 complains with this error:
error: no match for ‘operator==’ in ‘wrapper<std::basic_string<char> >(std::basic_string<char>(((const std::basic_string<char>&)((const std::basic_string<char>*)(& t))))) == wrapper<std::basic_string<char> >(std::basic_string<char>(((const std::basic_string<char>&)((const std::basic_string<char>*)(& t)))))’
What is interesting is that GCC triple-casts the template then fails to use operator == that was defined for std::string.
I don't think that implicit coercion is impossible, since if I change std::string to int or double, bool or anything primitive, GCC will choose the correct operator.
I do not want to define operator == for the wrapper struct, because that operator is just an example, and I need wrapper to 'feel' just like the real type regarding operators.
Just in cast GCC misunderstands my syntax, if I create a wrapper and try to compare it to itself, GCC complains again (though without triple casting) that it cannot find a matching == operator:
typedef wrapper<std::string> string_wrapper;
string_wrapper tw(t);
assert(tw == tw);
error: no match for ‘operator==’ in ‘tw == tw’
Why can't GCC find and/or use std::string operator == std::string when wrapper provides the cast?
That operator T is called a "conversion operator" or "conversion function" instead of a cast. "Conversions" are implicit; casting is explicit.
The compiler can't find the operator== for std::string because the overload resolution rules don't allow that to happen. More details about what you're really trying to do could help provide a solution.
Apparently this is a GCC 4.5 bug. The code is valid, unlike what Fred Nurk says.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45383
The questioner has answered itself with some GCC PR, but which really does not answer his question.
The reason is like #Fred describes. Reducing it:
template<typename T>
struct A {
operator T() { return T(); }
};
int main() {
A<std::string>() == A<std::string>();
}
What can the compiler do? It could call operator std::string() on both operands and then do the comparison. But why should it do that call in the first place? It first needs to find an operator== that has two parameters of type std::string. Let's look at how its operator is defined
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT,traits,Allocator>& lhs,
const basic_string<charT,traits,Allocator>& rhs);
There we have it. It first needs to do template argument deduction, and the fact that A does not match const basic_string<> will make it so that this operator== is ignored. You are lucky that operator== is found anyway using ADL so that it does argument deduction in the first place (since std::string is a template argument of your type, it will consider namespace std by ADL and find this operator).
So we have no suitable operator== to call and therefor GCC is alright with rejecting your code for the reasons #Fred gave in a nutshell. In the end, trying to make a class behave like another type is deemed to failure.