Why G++ cannot resolve the scope of this apparently easy ambiguity when attempting to polymorphysm with CRTP? - crtp

I am attempting to create template classes where each can solve a specific facet of the problem so to be able to mishmash them without resorting to creating the traditional abstract virtual classes.
For that, I believe CRTP would be the best paradigm.
However, when using CRTP a bit more I found trapped on this weak resolution logic - compiler (g++ 4.8.2) cannot distinguish between two methods on different classes even though their signature is different - only the method name is the same.
The classes implementation:
template< class T >
class A {
public:
void foo( uint32_t val ) {
T* me = static_cast<T*>( this );
me->doit();
}
};
template< class T >
class B {
public:
void foo() {
uint32_t v32 = 10;
T* me = static_cast<T*>( this );
me->foo( v32 );
}
};
class Derived : public A<Derived>,
public B<Derived>
{
public:
void doit() {
std::cout << "here" << std::endl;
}
};
Then it is used as
Derived d;
d.foo();
When compiled, this error surfaces:
$ g++ -std=c++11 -c testLambda.cpp
testLambda.cpp: In function ‘int main(int, char**)’:
testLambda.cpp:102:7: error: request for member ‘foo’ is ambiguous
d.foo();
^
testLambda.cpp:25:10: note: candidates are: void B<T>::foo() [with T = Derived]
void foo() {
^
testLambda.cpp:16:10: note: void A<T>::foo(uint32_t) [with T = Derived; uint32_t = unsigned int]
void foo( uint32_t val ) {
Is this a compiler bug or the actual expected result?

User pubby8 at reddit.com/r/cpp responded (quote) a quick fix is to add this to Derived's class body:
using A<Derived>::foo;
using B<Derived>::foo;

Related

function template specialization for variadic templated function (printf)

I have some Arduino C++11 code that I'm trying to improve: trying to make a printf-like function treat String specially so I don't have to call c_str() myself everywhere I use it. Basically for any builtin type like int float bool etc, I just want to pass the arg as-is, and for String, pass return the c_str(). Hit some snags so I tried this in some of the online compilers available. Starting point is this, using std::string instead of String:
#include <string>
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, args...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting.c_str());
}
So I tried creating a function template that just returns the value it gets, with a specialization for std::string:
#include <string>
template <typename T, typename R=T> R raw(T& x) {return x;}
template <> const char* raw<>(std::string& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
I get a compilation error when I run this in https://repl.it/languages/cpp11:
clang version 7.0.0-3~ubuntu0.18.04.1 (tags/RELEASE_700/final)
 clang++-7 -pthread -std=c++11 -o main main.cpp
main.cpp:10:25: error: cannot pass object of non-trivial type
'std::__cxx11::basic_string<char>' through variadic function; call will abort at
runtime [-Wnon-pod-varargs]
printf(msg, raw(args)...);
^
main.cpp:16:20: note: in instantiation of function template specialization
'SerialOut::error<int, std::__cxx11::basic_string<char> >' requested here
SerialOut::error("Message %d %s\n", 1, greeting);
^
1 error generated.
compiler exit status 1
With https://www.onlinegdb.com/online_c++_compiler there is no error but the raw() specialization is not selected, so the output for greeting is garbage.
In Arduino IDE I get a slightly different error (after replacing std::string by String, of course):
sketch\mqtt.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
sketch\sketch.ino.cpp.o: In function `char const* raw<String, char const*>(String&)':
sketch/utils.h:15: multiple definition of `char const* raw<String, char const*>(String&)'
sketch\Thermistor.cpp.o:sketch/utils.h:15: first defined here
I tried several variations on the raw() functions, to no avail. I figure I'm just missing a subtlety or it's just not possible to do this in C++11.
Update: I found Variadic Macro: cannot pass objects of non-trivially-copyable type through '...', one of the answers solves the above in C++14 (basically use decltype(auto) and overload instead of specialization). I added a slight variation on it that works also in C++11, and with "inline" it also works in Arduino C++ (without "inline" on the overload, the above message about multiple definitions -- turns out this is a linker message so it does compile, I guess the Arduino variant doesn't inline "obviously inlined" functions as other compilers).
Something along these lines, perhaps:
template <typename T>
struct SerialHelper {
static T raw(T val) { return val; }
};
template <>
struct SerialHelper<std::string> {
static const char* raw(const std::string& val) { return val.c_str(); }
};
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, SerialHelper<Ts>::raw(args)...);
}
};
Demo
Based on Variadic Macro: cannot pass objects of non-trivially-copyable type through '...' I got it to work with this very simple change, which works in C++11 and Arduino C++:
#include <string>
template <typename T> T raw(const T& x) {return x;}
inline const char* raw(const String& x) {return x.c_str();}
class SerialOut {
public:
template<class ...Ts>
static void error(const char* msg, Ts... args) {
printf(msg, raw(args)...);
}
};
int main() {
std::string greeting("hi");
SerialOut::error("Message %d %s\n", 1, greeting);
}
Thanks to #IgorTandetnik comment, it is clear why.

Rcpp modules: Validator function for exposed constructors with same number of parameters

I would like to expose a C++ class with Rcpp modules that has two constructors with the same number of parameters. As documented in the Rcpp modules vignette, this can be achieved by using a validator function as the second argument to .constructor with the type
typedef bool (*ValidConstructor)(SEXP*,int);
Could somebody provide an example of how it is supposed to be used? In the vignette, there is only a TODO note that an example should be included there.
To follow up on nrussell's answer, you might want to generate the validators from templates, i.e.
template <typename T0, typename T1>
bool typed_valid( SEXP* args, int nargs ){
return nargs == 2 && Rcpp::is<T0>(args[0]) && Rcpp::is<T1>(args[1]) ;
}
which you would use as:
.constructor<int, int>( & typed_valid<int,int> )
obviously the typed_valid function template is straightforward to generalize with variadic templates.
With the disclaimer that I haven't personally used this before, the following appears to work:
#include <Rcpp.h>
using namespace Rcpp;
class Example {
public:
Example(int x_, int y_)
: x(x_), y(y_)
{
Rcout << __PRETTY_FUNCTION__ << "\n";
}
Example(std::string x_, std::string y_)
: x(x_.size()), y(y_.size())
{
Rcout << __PRETTY_FUNCTION__ << "\n";
}
int add() const
{ return x + y; }
private:
int x, y;
};
bool validate_int_int(SEXP* args, int nargs)
{ return TYPEOF(args[0]) == INTSXP && TYPEOF(args[1]) == INTSXP; }
bool validate_string_string(SEXP* args, int nargs)
{ return TYPEOF(args[0]) == STRSXP && TYPEOF(args[1]) == STRSXP; }
RCPP_MODULE(ExampleMod) {
class_<Example>("Example")
.constructor<int, int>(
"(int, int) constructor",
validate_int_int
)
.constructor<std::string, std::string>(
"(string, string) constructor",
validate_string_string
)
.method("add", &Example::add)
;
}
Testing from R,
ex.int <- new(Example, 1L, 2L)
# Example::Example(int, int)
ex.string <- new(Example, "one", "two")
# Example::Example(std::string, std::string)
ex.int$add()
# [1] 3
ex.string$add()
# [1] 6
In each of validate_int_int and validate_string_string we are just testing the input SEXP types against the signatures of their corresponding constructors.
Following the footsteps of previous answers, I found there is a chance that a universal validator function might exist by using variadic template in cpp.
The implementation is shorter than I have expected though there are many technical details beyond the scope of this post.
template <typename... Types>
bool universal_validator(SEXP* args, int nargs) {
return universal_validator<Types...>(args, nargs, 0);
}
template <typename T = void, typename... Types>
bool universal_validator(SEXP* args, int nargs, int idx) {
if (idx>=nargs) return false;
// optional type traits
typedef typename Rcpp::traits::remove_const_and_reference<T>::type _Tp;
return Rcpp::is<_Tp>(args[idx]) && universal_validator<Types...>(args, nargs, idx+1);
}
template <>
bool universal_validator<>(SEXP* args, int nargs, int idx) {
return nargs == idx;
}
The usage of this universal_validator is quite simple. Given the Example class, the constructors in the RCPP_MODULE will become as follows.
RCPP_MODULE(example_module) {
Rcpp::class_<Example>("Example")
.constructor<int, int>("(int, int) constructor",
universal_validator<int, int>)
.constructor<std::string, std::string> ("(string, string) constructor",
universal_validator<std::string, std::string>)
.method("add", &Example::add)
;
}
Just put the same argument types as the constructor in the validator template, e.g. universal_validator<int, int> will do the job. And this shall work as long as Rcpp::is<T> is defined for any type T.
The source code from github
SEXP newInstance( SEXP* args, int nargs ) indicates that the validator must check the types of SEXP* and nargs simultaneously. That's why not only the type but also the index of SEXP* is also checked in all functions.

C++11 std::thread accepting function with rvalue parameter

I have some homework, and I have troubles understanding, (probably) how passing parameters to std::thread constructor works.
Assume following code (I deleted unneeded parts)
template<typename T, typename Task>
class Scheduler
{
private:
typedef std::unordered_map<std::size_t, T> Results;
class Solver
{
public:
Solver(Task&& task) : m_thread(&Solver::thread_function, std::move(task))
{
m_thread.detach();
}
Solver(Solver&& solver) = default; // required for vector::emplace_back
~Solver() = default;
private:
void thread_function(Task&& task)
{
task();
}
std::thread m_thread;
};
public:
Scheduler() = default;
~Scheduler() = default;
void add_task(Task&& task)
{
m_solvers.emplace_back(std::move(task));
}
private:
std::vector<Solver> m_solvers;
};
template<typename T>
struct Ftor
{
explicit Ftor(const T& t) : data(t) { }
T operator()() { std::cout << "Computed" << std::endl; return data; }
T data;
};
int main()
{
Scheduler<int, Ftor<int>> scheduler_ftor;
Scheduler<int, std::function<int(void)>> scheduler_lambda;
Ftor<int> s(5);
scheduler_ftor.add_task(std::move(s));
scheduler_lambda.add_task([](){ std::cout << "Computed" << std::endl; return 1; });
}
Why it doesn't compile?
MVS2015 is complaining about
functional(1195): error C2064: term does not evaluate to a function taking 1 arguments
functional(1195): note: class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
note: while compiling class template member function 'Scheduler<int,Ftor<int> >::Solver::Solver(Task &&)'
While G++ 4.9.2
functional: In instantiation of ‘struct std::_Bind_simple<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’:
required from ‘void Scheduler<T, Task>::add_task(Task&&) [with T = int; Task = Ftor<int>]’
functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<std::_Mem_fn<void (Scheduler<int, Ftor<int> >::Solver::*)(Ftor<int>&&)>(Ftor<int>)>’
typedef typename result_of<_Callable(_Args...)>::type result_type;
I suppose there are some problems with std::moving to std::thread.
If you use member function as first thread argument, second argument supposed to be this pointer, pointing to the object to which member function could be called to
UPDATE
Good discussion here
Start thread with member function
I don't follow your code, but addressing the question, a extrapolated answer will be( most of the code is psuedocode)
lets assume that there is a function int test(int name).
thread t0;
t0 = thread(test,32);
thread t1(test,43);
Passing a argument to function.
int temp = 0;
int testfunc(int& q)
{
cout<<q;
}
thread t1;
t1 = thread(testfunc,ref(temp));
In short, you just pass the name of the function that must be run in the thread as the first argument, and the functions parameters follow it in same order as they are in the function definition, for passing by reference you can use the ref() wrapper.See the below example.
#include <iostream>
#include <thread>
#include <string>
using namespace std;
void test(int a,int &a,string test)
{
\\do something
}
int main()
{
int test1 = 0;
string tt = "hello";
thread t1;
t1 = thread(23,&test1,tt);
t1.detach();
return 0;
}
if you are wondering about the use of join() and detach(), refer to this thread: When should I use std::thread::detach?, refer to my answer post in that thread.

How do I pass a struct by reference in WinRT Component C++/CX

I have the following in my WinRT component:
public value struct WinRTStruct
{
int x;
int y;
};
public ref class WinRTComponent sealed
{
public:
WinRTComponent();
int TestPointerParam(WinRTStruct * wintRTStruct);
};
int WinRTComponent::TestPointerParam(WinRTStruct * wintRTStruct)
{
wintRTStruct->y = wintRTStruct->y + 100;
return wintRTStruct->x;
}
But, it seems that the value of winRTStruct->y and x are always 0 inside the method, when called from C#:
WinRTComponent comp = new WinRTComponent();
WinRTStruct winRTStruct;
winRTStruct.x = 100;
winRTStruct.y = 200;
comp.TestPointerParam(out winRTStruct);
textBlock8.Text = winRTStruct.y.ToString();
What is the correct way to pass a struct by reference so it an be updated inside the method of a WinRTComponent written in C++/CX?
You cannot pass a struct by reference. All value types (including structs) in winrt are passed by value. Winrt structs are expected to be relatively small - they're intended to be used for holding things like Point and Rect.
In your case, you've indicated that the struct is an "out" parameter - an "out" parameter is write-only, its contents are ignored on input and are copied out on return. If you want a structure to be in and out, split it into two parameters - one "in" parameter and another "out" parameter (in/out parameters are not allowed in WinRT because they don't project to JS the way you expect them to project).
My co-worker helped me solve this.
In WinRT components, it seems that the best way to do this is to define a ref struct instead of a value struct:
public ref struct WinRTStruct2 sealed
{
private: int _x;
public:
property int X
{
int get(){ return _x; }
void set(int value){ _x = value; }
}
private: int _y;
public:
property int Y
{
int get(){ return _y; }
void set(int value){ _y = value; }
}
};
But this creates other problems. Now the VS11 compiler gives INTERNAL COMPILER ERROR when I try to add a method to the ref struct that returns an instance of the struct.

Question about custom I/O operators in C++?

I have the following piece of code:
class Student {
public:
Student(){}
void display() const{}
friend istream& operator>>(istream& is, Student& s){return is;}
friend ostream& operator<<(ostream& os, const Student& s){return os; }
};
int main()
{
Student st;
cin >> st;
cout << st;
getch();
return 0;
}
I have tried myself when omitting the friend keywords to make the operators become the member function of the Student class, then the compiler would produce "binary 'operator >>' has too many parameters". I have read some document saying that happened because all member functions always receive an implicit parameter "this" (that's why all member functions can access private variables).
Based on that explanation, I have tried as follows:
class Student {
public:
Student(){}
void display() const{}
istream& operator>>(istream& is){return is;}
ostream& operator<<(ostream& os){return os; }
};
int main()
{
Student st;
cin >> st;
cout << st;
getch();
return 0;
}
And got the error message: "error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'Student' (or there is no acceptable conversion)"
Can anyone give me a clear explanation, please?
You can't say that the function is a friend function, and then include the function in-line. The friend keyword implies that the function is not defined in the class, but it can access all the private and protected variables of the class. Change your code to:
class Student {
public:
Student(){}
void display() const{}
friend istream& operator>>(istream& is, Student& s);
friend ostream& operator<<(ostream& os, const Student& s);
};
istream& operator >>(istream& is, Student& s) { return is; }
ostream& operator <<(ostream& os, const Student& s) { return os; }
Look at http://www.java2s.com/Code/Cpp/Overload/Overloadstreamoperator.htm for another example.
With << and >>, the left hand operand is always a file stream, so you cannot overload them within your actual class (it'd technically have to go in the file stream class).
I forget where that operator is defined, but it would either be the global operator>>, or the operator belonging to the stream.
Defining it in Student is the wrong place.

Resources