Why is this a compiler error? (g++) - c++

So I'm attempting to utilize a generic compare functor in my utility class.
I attempt to define it and call it like so
template <class T>
bool AVL_tree<T>::avl_insert(AVL_Node<T> *& top, const AVL_Node<T> * insertNode, bool & taller) {
std::binary_function<T,T,bool>::first_argument_type insertNodeValue;
insertNodeValue = insertNode->data;
std::binary_function<T,T,bool>::second_argument_type topValue;
topValue = insertNode->data;
std::binary_function<T,T,bool>::result_type cmp_result;
cmp_result = comparer(insertNodeValue,topValue);
std::binary_function<T,T,bool>::result_type cmp_result2;
cmp_result2 = comparer(topValue,insertNodeValue);
//Function continues from here
}
The specific compiler error is expected ; before insertNodeValue
This error is repeated for topValue and cmp_result;
I don't really understand why this is a syntax error, I'm working off this reference:
http://www.cplusplus.com/reference/std/functional/binary_function/

It's a dependent name, so it requires the typename keyword:
typename std::binary_function<T,T,bool>::first_argument_type insertNodeValue;
Similarly for others. See the SO FAQ entry on dependent names.

Given that these are dependent types, your first step should probably be to add typename:
typename std::binary_function<T,T,bool>::first_argument_type insertNodeValue;

Related

Detect operator++ signature with std::is_detected_exact

I want to detect at compile time if a given type has the pre-increment operator with the library fundamentals TS v2 type_traits' is_detected_exact helper - however, it seems like I either misunderstood this helper or I supplied the wrong parameters, the following code does not compile:
#include <experimental/type_traits>
template<typename T>
using operator_plusplus_t = decltype(&T::operator++);
template<typename T>
using has_pre_increment = std::experimental::is_detected_exact<T&, operator_plusplus_t, T>;
struct incrementer
{
incrementer& operator++() { return *this; };
};
static_assert(has_pre_increment<incrementer>::value, "type does not have pre increment");
The error I get is this one (the static_assert fails):
<source>:14:15: error: static assertion failed: type does not have pre increment
static_assert(has_pre_increment<incrementer>::value, "type does not have pre increment");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiler returned: 1
https://godbolt.org/z/-zoUd9
I was expecting this code to compile since the "incrementer" struct has a operator++ method with no arguments returning a reference to its type ...
Maybe you can point me in the right direction, thanks in advance!
You can use decltype(++std::declval<T>()) instead.
https://godbolt.org/z/h_INw-

How to compile-time detect functions that overloaded important template?

Suppose we have a template:
template <class T>
void VeryImportantFunction(T t) {
// something
}
Somewhere it is called with something like:
// ..
int a = 12345;
VeryImportantFunction(a);
// ..
It is very big project with tons of source code, and occasionally somewhere in deep of the code appears a new header with overloaded function:
void VeryImportantFunction(int t) {
// totally another behavior
}
And code fragment above will call overloaded function, because it have more priority.
Can we somehow disable or in another way compile-time detect functions that can overload our important template?
Your question is unclear, but here's my take on it.
If you want to hit the template overload, you can simply invoke the function by explicitly specifying the template parameters:
int a = 12345;
VeryImportantFunction<int>(a);
If you want this from happening again in the future, then make VeryImportantFunction either a lambda or a struct - those cannot be overloaded "externally":
inline const auto VeryImportantFunction = [](auto x){ /* ... */ };
// no one can overload this!
If you want to know all the overloads of VeryImportantFunction without external tooling, then call it in a completely wrong way - the compiler error will likely show all considered overloads:
VeryImportantFunction(5, 5, 5, 5);
// error... will likely show all candidates
Write
inline void VeryImportantFunction(int t)
{
VeryImportantFunction<int>(t); // call the template function
}
immediately after your template definition.
Then if someone has written their own version of void VeryImportantFunction(int t), you'll get a compiler error.

error in making the file: expected primary-expression before ')' token

I have a struct defined as:
template<typename T>
struct unique_owned_item_filter: public std::unary_function<T,bool> {
unique_owned_item_filter(){}
bool operator()(const T& item)const {
return !item->shared() || item->owner() == MPI::COMM_WORLD.Get_rank();
}
typedef T item_type;
};
and I want to use this structure in a function like this
void read_nodes(std::ifstream& infile, mesh_type& mesh, const std::list<int>&my_nodes)
{
typedef typename mesh_type::node_t nd_t;
..... follows some code .....
create_double_nodes(mesh,unique_owned_item_filter<nd_t>);
}
where the function create_double_nodes is defined as
template<typename mesh_type, typename rule_type >
void create_double_nodes(mesh_type& mesh,rule_type& rule){
.... follows some code ....
}
When I pass to create_double_nodes the argument unique_owned_item_filter I insert
its dependence on the template parameter nd_t, that, in my case, is the mesh node
of type mesh_type::node_t.
When I compile the whole, I get the error expected primary-expression before ')' token at the declaration of create_double_nodes(mesh,unique_owned_item_filter<nd_t>);.
It seems to me that the template argument is right.
Can somebody help me?
The problem in the definition of the create_double_nodes disappeared, but now the problem appeared inside the body of the function itself.
template<typename mesh_type, typename rule_type >
void create_double_nodes(mesh_type& mesh, const rule_type& rule){
typename mesh_type::nd_set_t::const_iterator it_first( mesh.nodes().begin());
while(it_first!=mesh.nodes().end()){
if(rule(*it_first))
....follows code ....
it_first++
}
when i apply the rule to the const iterator it does not accept it. The compilation gives the following error:
no match for call to '(const GALES::unique_owned_item_filter, 5, GALES::base_5_dofs> >) (GALES::fem_node, 5, GALES::base_5_dofs>* const&)'
with candidates
bool GALES::unique_owned_item_filter<T>::operator()(const T&) const [with T = GALES::fem_node<GALES::geometric_node<2>, 5, GALES::base_5_dofs>]
where
GALES::fem_node<GALES::geometric_node<2>, 5, GALES::base_5_dofs>
is the complete type of node of the mesh.
I cannot understand why the rule applied to a constant iterator is not accepted. If you need more details I will try to explain it better.
Thank you very much again.
unique_owned_item_filter<nd_t> is a type, but you're using it as a function argument, where a value is required. You probably wanted to create an object of this type instead:
create_double_nodes(mesh, unique_owned_item_filter<nd_t>());
// ^^ parens here!
This will not work as-is, though, because your function template create_double_nodes takes the second parameter by non-const reference, and such cannot bind to a temporary (such as the one created in my example above).
You have two solutions: either change create_double_nodes to take its parameter by const-reference, or create a named object for the argument:
unique_owned_item_filter<nd_t> filter;
create_double_nodes(mesh, filter);
1.Make it an object:
create_double_nodes(mesh,unique_owned_item_filter<nd_t>());
^^
2.Pass by const reference or value:
void create_double_nodes(mesh_type& mesh, const rule_type& rule){
^^^^^

How to use the auto and decltype keywords to ease template argument deduction?

I am implementing the Merge sort algorithm. The problem is when I try to use a vector of automatically deduced types within the algorithm.
template <typename TIterator, typename TCompare>
void mergeSort(TIterator begin, TIterator end, TCompare criterium)
{
//...
auto help = *begin; // help is a value (not a reference)
QVector<decltype(help)> leftPart; // now decltype(help) is also a value
//... // and not a reference
}
This works.
But once I make the algorithm pass the TIterators by constant reference, I get an error which I never got in my whole life:
template <typename TIterator, typename TCompare>
void mergeSort(const TIterator& begin, const TIterator& end, TCompare criterium)
{
//...
auto help = *begin; // help is a value (not a reference)
QVector<decltype(help)> leftPart; // now decltype(help) is also a value
//...
}
results in:
In function 'void mergeSort(const TIterator&, const TIterator&, TCompare)':
internal compiler error: in type_unification_real, at cp/pt.c:14176
I am using g++ 4.6.3 on Ubuntu
What went wrong?
An internal compiler error occurs whenever the compiler fails, which means that you found a bug. This is the reason while early adoption of new standards is usually called the bleeding edge: sometimes, it makes you bleed ;)
There might be something wrong with your code, or there might not. It's not possible to tell from this output alone. What is certain is that the compiler does not support it so you might want to change it instead.
In particular, lookup std::iterator_traits<> to see all the things you can deduce from an iterator's type:
typename std::iterator_traits<TIterator>::value_type help = *begin;
// ::reference
// ::pointer
// ...
By circumventing the automatic deduction, you will probably be able to get past the compiler bug.
Note: if you wish to report the bug, which is certainly laudable, you will be asked to produce a preprocessed file reproducing the issue. This file should be as small as possible. It can be generated using -E on the gcc command line and generally ends up with the .ii extension.

how to solve following problem in C++?

I have one template function which will take a pointer type and i have instantiated it before calling.
i have written function with its dummy implementation as follows:
template<T>fun_name( const T *p )
{
//written functionality which will give me class name that i will store into string Variable
e.g. i got output like this string Var = "First_class" or string Var = "Second_class"
//Using this class name i will call one function of that class
if(Var == "Fisrt_class")
{
First_class::static_function_name(p);
}
if(Var == "Second_class")
{
Second_class::static_function_name(p);
}
}
and in global scope i instantiated this function for two variables as like below:
template<first_class>static_function_name(const First_class *)
template<Second_class>static_function_name(const Second_class *)
above code gives me error that
error: no matching function call in Second_class::static_function_class(const Fisrt_class*)
error: no matching function call in First_class::static_function_class(const Second_class*)
thanks in advance!
I think this :
template<typename T> // template<class T> is equally valid!
void fun_name( const T *p )
{
T::static_function_name(p);
}
is enough!
Two more errors is fixed in the above code:
Mention the keyword typename in template<T> in your code. You can also write template<class T> which is equally valid.
Mention the return type of the function template as well.
Your function template "calls" each of the static functions in each class. Even though program flow may never get to one of the calls, the compiler still has to figure out the code for each of them.
So when you instantiate:
template<first_class>fun_name(const first_class*)
the compiler tries to compile the entire function with T = first_class, which means at some point inside the function, it will try to compile the function call:
Second_class::static_function_name(p);
But since variable p is a pointer to first_class, the compiler doesn't find the function.
If you want conditional compilation, try specializing your function instead so the compiler only compiles the function call you intended for each type:
template <T> fun_name (const T* p);
template <> fun_name<first_class>(const first_class* p) {
first_class::static_function_name(p);
}
template <> fun_name<second_class>(const second_class* p) {
second_class::static_function_name(p);
}
Alternatively, you can use member functions which seem to be intended for what you are trying to do here. Then you can create objects and call the functions directly:
first_class f;
second_class s;
f.function();
s.function();
try changing to ,
template<typename T>
void fun_name( const T *p )
{
T::static_function_name(p);
}