C++ error declaring std::pair inside template class - c++

I want to avoid using the std::pair() constructor or std::make_pair() functions while inserting into a map. I also want to know the success status of the insert operation, so I cannot use operator[]. I tried the following code but it produces a compile error.
template<typename TKey, typename TVal>
class Map
{
private :
std::map<TKey, TVal> m_holder;
public :
bool insert(TKey key, TVal val)
{
std::pair<std::map<TKey, TVal>::iterator, bool> ret;
/* ret = m_holder.insert(std::make_pair(key, val)); */
return 0;
}
};
int main()
{
return 0;
}
Error :
Hello.cpp: In member function `bool Map<TKey, TVal>::insert(TKey, TVal)':
Hello.cpp:13: error: type/value mismatch at argument 1 in template parameter list for `template<class _T1, class _T2> struct std::pair'
Hello.cpp:13: error: expected a type, got ` std::map<TKey,TVal,std::less<_Key>,std::allocator<std::pair<const _Key, _Tp> > >::iterator'
Hello.cpp:13: error: invalid type in declaration before ';' token
Help me solve the problem.

std::pair<typename std::map<TKey, TVal>::iterator, bool> ret;
// ~~~~~~~^

Related

Adding a struct into a map

I'm having trouble adding a struct into a map. I don't really understand the error.
There are 2 errors:
I can't declare a map with 'struct' type
I can't use insert to 'insert' my struct into the map
What am I doing wrong?
#include <iostream>
#include <map>
int main()
{
typedef struct
{
std::string stringVar;
unsigned unsignedVar;
float floatVar;
} MyTypeDefStruct;
MyTypeDefStruct myTypeDefStruct;
myTypeDefStruct.stringVar = "myStr";
myTypeDefStruct.unsignedVar = 1000;
myTypeDefStruct.floatVar = -10.0;
float anotherFloat = -20.0;
std::map<MyTypeDefStruct, float> myMap;
myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
return 0;
}
error:
test.cpp: In function 'int main()':
test.cpp:21:36: error: template argument for 'template<class _Tp> struct std::less' uses local type 'main()::MyTypeDefStruct'
std::map<MyTypeDefStruct, float> myMap;
^
test.cpp:21:36: error: trying to instantiate 'template<class _Tp> struct std::less'
test.cpp:21:36: error: template argument 3 is invalid
test.cpp:21:36: error: template argument for 'template<class _T1, class _T2> struct std::pair' uses local type 'const main()::MyTypeDefStruct'
test.cpp:21:36: error: trying to instantiate 'template<class _T1, class _T2> struct std::pair'
test.cpp:21:36: error: template argument 4 is invalid
test.cpp:21:43: error: invalid type in declaration before ';' token
std::map<MyTypeDefStruct, float> myMap;
^
test.cpp:23:11: error: request for member 'insert' in 'myMap', which is of non-class type 'int'
myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
^
test.cpp:23:50: error: template argument for 'template<class _T1, class _T2> struct std::pair' uses local type 'main()::MyTypeDefStruct'
myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
^
test.cpp:23:50: error: trying to instantiate 'template<class _T1, class _T2> struct std::pair'
There are several issues in your code:
The struct should defined outside of the function main, can't see a reason why you want to define it there in this case, and since it is local inside of main, you can't use it anywhere else!
You are using the C-style typedef struct ... StructName instead of simply using struct MyStruct.
Your struct doesn't implement the operator<, hence, since std::map is an ordered map, and it doesn't have anyway to compare two keys (here, the key is your struct), it doesn't able to insert any pair.
Your struct doesn't implement the operator== which is important to actually retrieving the value of a certain key... You should be able to check if the keys are similar.
Another small fix - using std::make_pair instead of its ctor.
Your code should look like:
#include <iostream>
#include <map>
struct MyStruct
{
std::string stringVar;
unsigned unsignedVar;
float floatVar;
friend bool operator<(const MyStruct& l, const MyStruct& r)
{
return std::tie(l.stringVar, l.unsignedVar, l.floatVar)
< std::tie(r.stringVar, r.unsignedVar, r.floatVar);
}
friend bool operator==(const MyStruct& l, const MyStruct& r)
{
return std::tie(l.stringVar, l.unsignedVar, l.floatVar)
== std::tie(r.stringVar, r.unsignedVar, r.floatVar);
}
};
int main()
{
MyStruct my_struct;
my_struct.stringVar = "myStr";
my_struct.unsignedVar = 1000;
my_struct.floatVar = -10.0;
float anotherFloat = -20.0;
std::map<MyStruct, float> myMap;
myMap.insert(std::make_pair(my_struct, anotherFloat));
return 0;
}
How did I get to identifying the first problem? In the first error (always look at the first error, the others may be misleading!), it is written:
test.cpp:21:36: error: template argument for 'template<class _Tp> struct std::less' uses local type 'main()::MyTypeDefStruct'
std::map<MyTypeDefStruct, float> myMap;
Notice that the template initialization here is using main()::MyTypeDefStruct and not MyTypeDefStruct!!! These types are different, and the first is available only in the scope of main()!
The third point is because when you fix the first point, you will get:
error: no match for 'operator<' (operand types are 'const MyStruct' and 'const MyStruct')
The first problem is that map requires a way to compare two myTypeDefStructs.
You'll need to do is define operator< or std::less for your class, or pass a comparison functor to the map.
std::map<T>::insert uses a comparator to insert your elements but there is no one defined for your struct, hence try to use something like the following
#include <iostream>
#include <map>
struct MyTypeDefStruct
{
std::string stringVar;
unsigned unsignedVar;
float floatVar;
} ;
bool operator<(const MyTypeDefStruct& lhs, const MyTypeDefStruct& rhs){
return lhs.unsignedVar < rhs.unsignedVar;
}
int main()
{
MyTypeDefStruct myTypeDefStruct;
myTypeDefStruct.stringVar = "myStr";
myTypeDefStruct.unsignedVar = 1000;
myTypeDefStruct.floatVar = -10.0;
float anotherFloat = -20.0;
std::map<MyTypeDefStruct, float> myMap;
myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
return 0;
}
A sorted map needs a less operator (operator<) to sort the elements. You have to provide such operator or you have to set a sort function. One possible solution is to implement this operator:
#include <iostream>
#include <map>
struct MyTypeDefStruct {
std::string stringVar;
unsigned unsignedVar;
float floatVar;
};
bool operator<(const MyTypeDefStruct &lhs, const MyTypeDefStruct &rhs) {
if (lhs.stringVar < rhs.stringVar) return true;
if (lhs.stringVar > rhs.stringVar) return false;
if (lhs.unsignedVar < rhs.unsignedVar) return true;
if (lhs.unsignedVar > rhs.unsignedVar) return false;
if (lhs.floatVar < rhs.floatVar) return true;
return false;
}
int main() {
MyTypeDefStruct myTypeDefStruct;
myTypeDefStruct.stringVar = "myStr";
myTypeDefStruct.unsignedVar = 1000;
myTypeDefStruct.floatVar = -10.0;
float anotherFloat = -20.0;
std::map<MyTypeDefStruct, float> myMap;
myMap.insert(std::pair<MyTypeDefStruct, float> (myTypeDefStruct, anotherFloat));
return 0;
}

Error when template parameter passed to boost multi index container

I am trying to use multi_index_container with templates. below is my code.
template < class ValueType >
class anrQueue
{
private:
typedef boost::multi_index_container<
ValueType,
indexed_by<
sequenced<>,
ordered_unique<identity<ValueType> >
>
> a_queue;
a_queue mQueue;
public:
size_t remove(const ValueType& x) {
return mQueue.get<1>().erase(x);
}
-------------------------^
error: expected primary-expression before ‘)’ token
How to resolve this
Write:
return mQueue.template get<1>().erase(x);
Look here for an explanation on the usage of template on dependent contexts.

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.

error: no type named ‘value_type’ in ‘class

I am getting the following compiler error:
(graph_algorithms.h:59:111: error: no type named ‘value_type’ in ‘class Graph::graph_algorithms<int>::vertex_comparer’)
What does this mean?
The following line gives me a whole slew of compiler errors
std::priority_queue<typename Graph::graph<U>::vertex, typename Graph::graph_algorithms<U>::vertex_comparer> pri_que;
#ifndef GRAPH_ALGORIUHMS_H_
#define GRAPH_ALGORIUHMS_H_
#include <queue>
#include "graph.h"
namespace Graph
{
template <class U>
class graph_algorithms
{
// Forward declarations of
// internal classes
private :
class vertex_comparer;
public :
graph_algorithms(graph<U> &graph) :
m_Graph(graph)
{}
// List of algorithms to perform on graph
typename std::queue<U> &find_key_breadth_first(U key);
// Definition of internal classes
private :
class vertex_comparer
{
public:
bool operator()(typename graph<U>::vertex &v1, typename graph<U>::vertex &v2)
{
return (v1.key() < v2.key()) ? true : false;
}
};
private :
// Private member variables and methods
graph<U> &m_Graph;
std::queue<U> m_Queue;
void breadth_first_search(U key);
};
}
The comparison class should be the 3rd parameter of the std::priority_queue template, the second being a container (like std::vector<typename Graph::graph<U>::vertex>) which will have a value_type member.

"expected primary expression" error on template method using

I have some generic code which implements Pareto rule. It seems like well-formed code.
GCC 4.4 compiler messages about errors for newResult.set<Criterion>( criterion() ); expression. But I can't found problem.
Full error log:
trunk$ g++ -std=c++0x -o test test.cpp
t6.cpp: In member function ‘bool Pareto<Minimize<T>, Types ...>::operator()(Map&, Map&)’:
t6.cpp:24: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘)’ token
t6.cpp:26: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘)’ token
t6.cpp: In member function ‘bool Pareto<Maximize<T>, Types ...>::operator()(Map&, Map&)’:
t6.cpp:43: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘)’ token
t6.cpp:45: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘)’ token
Full code listing:
// TypeMap
template < typename ... Tail >
struct Holder;
template <typename ValueType, typename Head, typename ... Tail >
struct Holder<ValueType, Head, Tail ... > :
public Holder<ValueType, Head>,
public Holder<ValueType, Tail ... >
{};
template <typename ValueType, typename Head >
struct Holder<ValueType, Head>
{
ValueType value;
};
template < typename ... Types >
struct TypeMap;
template <typename ValueType, typename ... Types >
struct TypeMap<ValueType, Types ... > :
public Holder<ValueType, Types ... >
{
template <typename T>
void set(const ValueType& value)
{
((Holder<ValueType, T>*)this)->value = value;
}
template <typename T>
ValueType get()
{
return ((Holder<ValueType, T>*)this)->value;
}
};
// Objectives
template <typename Criterion> struct Maximize : public Criterion {};
template <typename Criterion> struct Minimize : public Criterion {};
// Criteria
struct Criterion1{ double operator()(){ return 0; }};
struct Criterion2{ double operator()(){ return 0; }};
// Pareto rule
template < typename ... Types > struct Pareto;
template < typename T, typename ... Types >
struct Pareto<Minimize<T>, Types ... >
{
template< typename Map >
bool operator()(Map& oldResult, Map& newResult)
{
typedef Minimize<T> Criterion;
Criterion criterion;
// ERROR HERE !!!
newResult.set<Criterion>( criterion() );
if(newResult.get<Criterion>() >= oldResult.get<Criterion>())
return false;
Pareto<Types ... > pareto;
return pareto(oldResult, newResult);
}
};
template < typename T, typename ... Types >
struct Pareto<Maximize<T>, Types ... >
{
template< typename Map >
bool operator()(Map& oldResult, Map& newResult)
{
typedef Maximize<T> Criterion;
Criterion criterion;
// ERROR HERE !!!
newResult.set<Criterion>( criterion() );
if(newResult.get<Criterion>() <= oldResult.get<Criterion>())
return false;
Pareto<Types ... > pareto;
return pareto(oldResult, newResult);
}
};
template<>
struct Pareto<>
{
template<typename Map>
bool operator()(Map& oldResult, Map& newResult)
{
oldResult = newResult;
return true;
}
};
int main()
{
TypeMap<double, Minimize<Criterion1>, Maximize<Criterion2>> oldResult, newResult;
Pareto<Minimize<Criterion1>, Maximize<Criterion2>> pareto;
pareto(oldResult, newResult);
}
Found it:
newResult.template set<Criterion>( criterion() );
if(newResult.template get<Criterion>() >= oldResult.template get<Criterion>())
return false;
You have to qualify the member function templates for the compiler in this case.
The lexer wouldn't be able to decide (at the time of template declaration, not instantiation) whether <Criterion means the start of a template parameter list or, instead, a comparison operator.
See
Using the template keyword as qualifier
What is the .template and ::template syntax about? (Comeau)
Standard, § 14.2, sub 4. and 5., noteworthy:
[ Note: As is the case with the typename prefix, the template prefix is allowed in cases where it is
not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the -> or . is not
dependent on a template-parameter, or the use does not appear in the scope of a template. —end note ]