LLVM vs MSVC function disambiguation - c++

A library that I'm porting from Visual Studio to Xcode uses a template chain. My chain works correctly in Visual Studio. However, when I compile it in Xcode using Apple LLVM 6.0, I get the error
References to overloaded function could not be resolved; did you mean to call it?
Update
I've created a standalone example that compiles in Visual Studio but fails to compile in Xcode with the same error that I'm seeing in my library.
Note: I can probably fix my library code by other means. However, I'd like to take this opportunity for someone to teach me something new about disambiguation and the differences between the compilers. Is this pattern non-standard? Did it only work in Visual Studio because of a language extension?
class Test1{};
class Test2{};
struct NullType{};
template< class T, int id>
class SpecialHandler
{
public:
enum { ETypeId = id };
void handlerFunc( float, int ){}
};
template<typename TReturn, class TObj, typename TParam1, typename TParam2>
class TestResolveClass
{
public:
template< TReturn (TObj::*Func)(TParam1, TParam2 ) >
inline static void funcThatFailsResolve(TObj* obj)
{
(void)obj;
(void)Func;
}
};
template< class TSpecialHandler, class TParent >
class Chain :
public TParent
{
public:
typedef TParent Parent;
typedef TestResolveClass<void, SpecialHandler<Test1, 1>, float, int> TestResolver1;
typedef TestResolveClass<void, SpecialHandler<Test2, 2>, float, int> TestResolver2;
typedef TestResolveClass< void, TSpecialHandler, float, int > TemplatedTestResolver;
void traverseChain()
{
Parent* parentPtr = static_cast<Parent*>( this );
parentPtr->traverseChain(); // up the chain we go
SpecialHandler<Test1, 1> testaroo;
TestResolver1::funcThatFailsResolve< &SpecialHandler<Test1, 1>::handlerFunc >( &testaroo ); // no error
TemplatedTestResolver::funcThatFailsResolve< //<-- Reference to overloaded function could not be resolved; did you mean to call it?
&TSpecialHandler::handlerFunc
>( &m_handler );
TemplatedTestResolver::funcThatFailsResolve< // <-- Reference to overloaded function could not be resolved; did you mean to call it?
static_cast<void (TSpecialHandler::*)( float, int )>( &TSpecialHandler::handlerFunc )
>( &m_handler );
}
private:
TSpecialHandler m_handler;
};
template<>
class Chain< NullType, NullType >
{
public:
void traverseChain(){}
};
typedef Chain< NullType, NullType > ChainLink0;
typedef Chain< SpecialHandler<Test1, 1>, ChainLink0 > ChainLink1;
typedef Chain< SpecialHandler<Test2, 2>, ChainLink1 > ChainLink2;
typedef ChainLink2 FullChain;
class ChainContainer :
public FullChain
{
public:
ChainContainer()
{
traverseChain();
}
};
int main()
{
ChainContainer test;
(void)test;
}
Thanks for your help.
Update 2: I changed a few of the names to be more useful and restructured the code to be clear where the problem is. I also placed some example code before the error to show a situation in which the error does not appear.

Related

C++ not recognizing 3points operator

I have the following code:
class IConfigItem
{
public:
virtual ~IConfigItem() {};
virtual operator int() const { return 0; }
virtual operator std::string () const { return std::string(); }
};
template< typename T > class ConfigItem : public IConfigItem
{
private:
T m_value;
public:
ConfigItem< T >(const T& valueIn = 0) : m_value(valueIn) {}
operator T() const
{
return m_value;
}
};
template< typename T, typename ...Args > std::unique_ptr< T > makeUnique(Args&& ...args)
{
return std::unique_ptr< T >(new T(std::forward< Args >(args)...));
}
and I am getting the following error:
Error 1 error C2143: syntax error : missing ',' before '...'
I do not get it why. Why doesn't it recognize the ...? What am I doing wrong? I have the same code on Ubuntu, and there it is working well, now I have copied this to VS2012 and it has errors. Please someone help me.
You need Visual Studio 2013 for this see Variadic templates in the Visual Studio c++11 features support page: http://msdn.microsoft.com/en-us/library/hh567368.aspx
The community version of Visual Studio 2013 is available here:
http://visualstudio.com/en-us/downloads

constexpr: saving calculation results [duplicate]

I'm trying to do the following (only relevant parts of code below):
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
static constexpr char* err_value = "Type is not a container model";
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
static_assert(false, IsContainerCheck<ResultType>::err_value)
return 0;
}
};
template<>
struct run<true_t> {
constexpr static int apply() {
return 0;
}
};
}
This fails because the static_assert allows only literals to be printed. The same is with BOOST_STATIC_ASSERT_MSG macro.
So my question is - is there any way to output a constexpr string during compilation?
If there is a gcc extension providing this functionality that would also be great.
Used compiler gcc 4.8.1
GCC does not provide such a mechanism as you want. However you will not need
it if you are able to refactor your code somewhat as illustrated in the
following program. (I have filled in a few gaps so as to give us a
compilable example):
#include <type_traits>
#include <vector>
template<typename ContainerType>
struct is_container
{
static bool const value = false;
};
template<>
struct is_container<std::vector<int>>
{
static bool const value = true;
};
template<typename ContainerType>
struct IsContainerCheck // : is_container<ContainerType> <- Uneccessary
{
static_assert(is_container<ContainerType>::value,
"Type is not a container model");
};
namespace _check_concept {
template<typename ResultType>
struct run {
constexpr static int apply() {
return (IsContainerCheck<ResultType>(),0);
}
};
// No such specialization is necessary. Delete it.
// template<>
// struct run<true_t> {
// constexpr static int apply() {
// return 0;
// }
//};
}
using namespace _check_concept;
int main(int argc, char **argv)
{
auto verdict0 = run<std::vector<int>>::apply();
(void)verdict0;
// The following line will static_assert: "Type is not a container model"
auto verdict1 = run<float>::apply();
(void)verdict1;
return 0;
}
In your specialization _check_concept::struct run<true_t> I presume that
true_t is not an alias or equivalent of std::true_type, but rather
just a place-holder for some ResultType that is a container type. As
the test program shows, no such specialization is now necessary, because
IsContainerCheck<ResultType>() will static_assert, or not, depending
on ResultType, in the unspecialized run<ResultType>::apply().
I had some time (and a good liqueur to come along with it) to think more about the problem. This is what I came up with:
namespace _details {
struct PassedCheck {
constexpr static int printError () {
return 0; //no error concept check passed
}
};
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept_impl;
template<template<typename> class ConceptCheck, typename FirstType, typename ...ModelTypes>
struct check_concept_impl<ConceptCheck, FirstType, ModelTypes...> : mpl::eval_if< typename ConceptCheck<FirstType>::type,
check_concept_impl<ConceptCheck, ModelTypes...>,
mpl::identity<ConceptCheck<FirstType>>>
{ };
template<template<typename> class ConceptCheck, typename LastType>
struct check_concept_impl<ConceptCheck, LastType> : mpl::eval_if<typename ConceptCheck<LastType>::type,
mpl::identity<PassedCheck>,
mpl::identity<ConceptCheck<LastType>>>
{ };
}
template<template<typename> class ConceptCheck, typename ...ModelTypes>
struct check_concept {
private:
typedef typename _details::check_concept_impl<ConceptCheck, ModelTypes...>::type result_type;
public:
// the constexpr method assert produces shorter, fixed depth (2) error messages than a nesting assert in the trait solution
// the error message is not trahsed with the stack of variadic template recursion
constexpr static int apply() {
return result_type::printError();
}
};
template<typename ContainerType>
struct IsContainerCheck : is_container<ContainerType>
{
template<typename BoolType = false_t>
constexpr static int printError () {
static_assert(BoolType::value, "Type is not a container model");
return 0;
}
};
and the usage:
check_concept<IsContainerCheck, std::vector<int>, std::vector<int>, float, int>::apply();
The solution is probably not the most elegant one but I it keeps the assert message short:
In file included from ../main.cpp:4:0:
../constraint.check.hpp: In instantiation of ‘static constexpr int IsContainerCheck::printError() [with BoolType = std::integral_constant; ContainerType = float]’:
../constraint.check.hpp:61:34: required from ‘static constexpr int check_concept::apply() [with ConceptCheck = IsContainerCheck; ModelTypes = {std::vector >, std::vector >, float, int}]’
../main.cpp:25:83: required from here
../constraint.check.hpp:74:3: error: static assertion failed: Type is not a container model
static_assert(BoolType::value, "Type is not a container model");
The assert is issued in a constexpr method after the check_concept template specialization has been done. Embedding the static assert directly into the template class definition would drag the whole check_concept_impl recursion stack into the error message.
So changing the IsContainerCheck trait to something like (rest of the changes omitted for readibility):
template<typename ContainerType>
struct IsContainerCheck
{
static_assert(is_container<ContainerType>::type::value, "Type is not a container model");
};
would yield an error
../constraint.check.hpp: In instantiation of ‘struct IsContainerCheck’:
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, float, int>’
/usr/include/boost/mpl/eval_if.hpp:38:31: required from ‘struct boost::mpl::eval_if, _details::check_concept_impl >, float, int>, boost::mpl::identity > > >’
../constraint.check.hpp:36:9: required from ‘struct _details::check_concept_impl >, std::vector >, float, int>’
../constraint.check.hpp:53:84: required from ‘struct check_concept >, std::vector >, float, int>’
../main.cpp:25:81: required from here
../constraint.check.hpp:72:2: error: static assertion failed: Type is not a container model
static_assert(is_container::type::value, "Type is not a container model");
As you can see each recursive eval_if call is emended in the error description which is bad because it makes the error message dependent from the amount and type of template parameters.

boost::signal slot_type with a template

I'm getting a build error when building for the following function:
template <class T> class Event {
public:
typedef boost::signal<void (void*, const T)> signal_t;
typedef boost::signals::connection connection_t;
public:
Event() { }
connection_t connect(signal_t::slot_type subscriber){
return signal.connect(subscriber);
}
}
error:
error: 'class boost::signal<void ()(void*, T), boost::last_value<typename boost::function_traits<void ()(void*, T)>::result_type>, int, std::less<int>, boost::function<void ()(void*, T)> >::slot_type' is not a type
I believe it has something to do with the fact that it's templated, but I'm not sure how to fix it. I've tried adding , such that
connection_t connect(signal_t::slot_type<T> subscriber)
But this just produceds another error.
Tell the compiler that it's a type with typename:
connection_t connect(typename signal_t::slot_type subscriber){
return signal.connect(subscriber);
}
The problem is that signal_t depends on the template parameter T, and so you need to explicitly tell the compiler that signal_t::slot_type is going to be a type.

Compilation error with Type Traits in boost::type_traits::conditional

I am having a problem in some code using type_traits from boost.
It is quite a complex part of the code, but I could isolate the part that gives the compilation error:
template<const size_t maxLen>
class MyString {
public:
typedef boost::conditional<(maxLen > 0), char[maxLen+1], std::string> ObjExternal;
};
template <class T>
class APIBase {
public:
typedef T obj_type;
typedef typename T::ObjExternal return_type;
};
template <class T>
int edit(const T& field, const typename T::return_type& value)
{
return 0;
}
int myFunction()
{
APIBase<MyString<10> > b;
char c[11];
return edit(b, c);
}
This gives the following error:
test.cpp: In function ‘int myFunction()’:
tes.cpp:109: error: no matching function for call to ‘edit(APIBase >&, char [11])’
tes.cpp:100: note: candidates are: int edit(const T&, const typename T::return_type&) [with T = APIBase >]
However, if I change the line with the code
char c[11];
by
MyString<10>::ObjExternal c;
it works. Similarly, if instead I change the line
typedef boost::conditional<(maxLen > 0), char[maxLen+1], std::string> ObjExternal;
by
typedef char ObjExternal[maxLen+1];
it also works. I am thinking that it is a problem with boost::conditional, as it seems it is not being evaluated right. Is there a problem in my code, or there is an alternative that can be used instead of boost::conditional to have this functionality?
I am thinking about using the 2nd option, but then I could not use maxLen as 0.
You need to use the member typedef type provided by conditional and not the conditional type itself.
Change:
typedef boost::conditional<(maxLen > 0),
char[maxLen+1],
std::string> ObjExternal;
to:
typedef typename boost::conditional<(maxLen > 0),
char[maxLen+1],
std::string>::type ObjExternal;

expected ';' after expression

I'm trying to port a project from Windows to Mac. I'm having troubles compiling the class CFactory. I'll try to illustrate the problem.
Here's what I have on my Factory.h
namespace BaseSubsystems
{
template <class T>
class CFactory
{
protected:
typedef T (*FunctionPointer)();
typedef std::pair<std::string,FunctionPointer> TStringFunctionPointerPair;
typedef std::map<std::string,FunctionPointer> TFunctionPointerMap;
TFunctionPointerMap _table;
public:
CFactory () {}
virtual ~CFactory();
}; // class CFactory
template <class T>
inline CFactory<T>::~CFactory()
{
TFunctionPointerMap::const_iterator it = _table.begin();
TFunctionPointerMap::const_iterator it2;
while( it != _table.end() )
{
it2 = it;
it++;
_table.erase(it2);
}
} // ~CFactory
}
When I'm trying to compile, the compiler complains:
Factory.h:95:44: error: expected ';' after expression [1]
TFunctionPointerMap::const_iterator it = _table.begin();
^
;
Why is this happening? That am I missing?
NOTE: This project compiles properly on MSVC.
Thanks.
You are missing the required typename keyword when referring to a dependent type. Microsoft Visual Studio incorrectly accepts your code without the typename (this is a well known mistake in VS that will never be corrected).
typename TFunctionPointerMap::const_iterator it;