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 ]
Related
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.
I'm currently reading Bjarne Stroustrup's "The C++ Programming Language" 4th Edition. In the first parts of the book, I found an usage of using looks like following:
// Error is in these 2 lines
template<typename T>
using Iterator<T> = typename T::iterator;
*see [**] for complete program and error message*
This is exactly what I found in the page 105. When I turned this into a complete program and tried to compile it, g++ gave me this error masseage:
> g++ -std=c++14 -o fnd find_all.cpp
find_all.cpp:13:15: error: expected '=' before '<' token
using Iterator<T> = typename T::iterator;
^
find_all.cpp:13:15: error: expected type-specifier before '<' token
I can't find any problem in this code, (I'm new to C++, I can't find the problem with my little knowledge)( More confusingly I found this on Bjarne's book )
Could someone tell me why does that code makes an error?
NOTE: However If I replaced Iterator<C> with typename C::iterator (see below), It works fine, there is no error!
[**]Complete Program and Error Message:
// Error is in these 2 lines
template<typename T>
using Iterator<T> = typename T::iterator;
// -------------------------------------------
// For the completeness I'll include my complete program here
template<typename C, typename V>
vector<Iterator<C>> find_all(C& c, V v) // find all occurrences of v in c
{
vector<Iterator<C>> res;
for (auto p = c.begin(); p!=c.end(); ++p)
if (∗p==v)
res.push_back(p);
return res;
}
void test()
{
string m {"Mary had a little lamb"};
for (auto p : find_all(m, 'a'))
if (*p == 'a')
cerr << "string bug!\n";
list<double> ld { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 1.1, 1.1 };
for (auto p : find_all(ld, 1.1))
if (*p == 1.1)
cerr << "list bug!\n";
vector<string> strv { "blue", "yellow", "red", "white", "orange", "blue" };
for (auto p : find_all(strv, "blue"))
if (*p == "blue")
cerr << "string vector bug!\n";
}
int main(void)
{
test();
return 0;
}
ERROR MESSAGE:
> g++ -std=c++14 -o fnd find_all.cpp
find_all.cpp:13:15: error: expected '=' before '<' token
using Iterator<T> = typename T::iterator;
^
find_all.cpp:13:15: error: expected type-specifier before '<' token
find_all.cpp:16:8: error: 'Iterator' was not declared in this scope
vector<Iterator<C>> find_all(C& c, V v)
^
find_all.cpp:16:17: error: template argument 1 is invalid
vector<Iterator<C>> find_all(C& c, V v)
^
find_all.cpp:16:17: error: template argument 2 is invalid
find_all.cpp:16:18: error: expected unqualified-id before '>' token
vector<Iterator<C>> find_all(C& c, V v)
^
find_all.cpp: In function 'void test()':
find_all.cpp:30:31: error: 'find_all' was not declared in this scope
for (auto p : find_all(m, 'a'))
^
find_all.cpp:35:32: error: 'find_all' was not declared in this scope
for (auto p : find_all(ld, 1.1))
^
find_all.cpp:40:37: error: 'find_all' was not declared in this scope
for (auto p : find_all(strv, "blue"))
First <T> must be omitted
template<typename T>
using Iterator = typename T::iterator;
When you define a class template or function template, you use:
template <typename T> struct Foo { };
template <typename T> T bar() { return T{}; }
You don't use Foo<T> or bar<T> when defining the templates.
Similarly, when using templates to define an alias, you need to use:
template <typename T>
using Iterator = typename T::iterator;
^^ Don't include <T>
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;
// ~~~~~~~^
I want to write something to share memory,
pAttr is the share memory address.
The template function as below,
but it does not pass the compile.
template <typename Container>
int ShareMemMgn::writeContainerToShareMemMap(void* pAttr, Container& oData)
{
typename Container::mapped_type T;
(T*)(pElem) = (T *)(pAttr); //compile errror
/*
share_mem_mgn.cpp:545: error: expected primary-expression before ‘)’ token
share_mem_mgn.cpp:545: error: ‘pElem’ was not declared in this scope
share_mem_mgn.cpp:545: error: expected primary-expression before ‘)’ token
*/
for(typename Container::iterator it = oData.begin();
it != oData.end(); ++it)
{
memcpy(pElem, (&(it->second)), sizeof(typename Container::mapped_type));
++pElem;
}
return 0;
}
How to get the maped type pointer?
Could anyone help me?
Thanks a lot.
As your code reads right now, T is a variable, not a type. Presumably you meant this:
typedef typename Container::mapped_type T;
T * pElem = static_cast<T *>(pAttr);
You could also do this
template <typename KeyType, typename ValueType>
int ShareMemMgn::writeContainerToShareMemMap(void* pAttr, std::map<KeyType,ValueType>& oData)
If you are using only a Map.
How is one supposed to use a std container's value_type?
I tried to use it like so:
#include <vector>
using namespace std;
template <typename T>
class TSContainer {
private:
T container;
public:
void push(T::value_type& item)
{
container.push_back(item);
}
T::value_type pop()
{
T::value_type item = container.pop_front();
return item;
}
};
int main()
{
int i = 1;
TSContainer<vector<int> > tsc;
tsc.push(i);
int v = tsc.pop();
}
But this results in:
prog.cpp:10: error: ‘T::value_type’ is not a type
prog.cpp:14: error: type ‘T’ is not derived from type ‘TSContainer<T>’
prog.cpp:14: error: expected ‘;’ before ‘pop’
prog.cpp:19: error: expected `;' before ‘}’ token
prog.cpp: In function ‘int main()’:
prog.cpp:25: error: ‘class TSContainer<std::vector<int, std::allocator<int> > >’ has no member named ‘pop’
prog.cpp:25: warning: unused variable ‘v’
I thought this was what ::value_type was for?
You have to use typename:
typename T::value_type pop()
and so on.
The reason is that the compiler cannot know whether T::value_type is a type of a member variable (nobody hinders you from defining a type struct X { int value_type; }; and pass that to the template). However without that function, the code could not be parsed (because the meaning of constructs changes depending on whether some identifier designates a type or a variable, e.g.T * p may be a multiplication or a pointer declaration). Therefore the rule is that everything which might be either type or variable and is not explicitly marked as type by prefixing it with typename is considered a variable.
Use the typename keyword to indicate that it's really a type.
void push(typename T::value_type& item)
typename T::value_type pop()
Here is a full implementation of the accepted answers above, in case it helps anyone.
#include <iostream>
#include <list>
template <typename T>
class C1 {
private:
T container;
typedef typename T::value_type CT;
public:
void push(CT& item) {
container.push_back(item);
}
CT pop (void) {
CT item = container.front();
container.pop_front();
return item;
}
};
int main() {
int i = 1;
C1<std::list<int> > c;
c.push(i);
std::cout << c.pop() << std::endl;
}
A fairly common practice is to provide an alias representing the underlying value type for convenience.
template <typename T>
class TSContainer {
private:
T container;
public:
using value_type = typename T::value_type;
void push(value_type& item)
{
container.push_back(item);
}
value_type pop()
{
value_type item = container.pop_front();
return item;
}
};