Inheriting std::stack causes an error with clang but works with gcc - c++

Irrelevant. See update below.
I've been playing around with std::stack and noticed something strange. Here's the code:
.h file
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>> {};
struct Simple {
std::string txt = "txt";
};
.cpp file
int main () {
Simple smpl;
auto vec = VecOfRef<Simple>{std::ref(smpl)};
auto stdStack = std::stack<Simple,decltype(vec)>(vec); //works fine
auto myStack = Stack<Simple>(vec); //error
//to check if a reference is stored
stdStack.push(smpl);
smpl.txt.append("append");
Simple& r = sStack.top();
cout << r.txt << endl;
return 0;
}
The error message says:
19:
No matching conversion for functional-style cast from
'std::__1::vector,
std::__1::allocator > >' to
'Stack'
UPDATE:
I have been playing around with this and managed to almost get the code to work:
#include <vector>
#include <string>
#include <stack>
#include <iostream>
#include <functional>
template<typename Tp> using VecOfRef = std::vector<std::reference_wrapper<Tp>>;
template <typename T>
class Stack : public std::stack<T,VecOfRef<T>> {
public:
using std::stack<T,VecOfRef<T>>::stack;
using std::stack<T,VecOfRef<T>>::c;
T& top() {
return c.back().get();
}
};
struct Simple {
std::string txt = "txt";
void print() { std::cout << txt << std::endl; }
};
int main() {
Simple smpl;
Simple smpl_2;
Simple smpl_3;
VecOfRef<Simple> vr {smpl,smpl_2,smpl_3};
// auto myStack = Stack<Simple> (vr); // error
auto myStack = Stack<Simple> ({smpl,smpl_2,smpl_3}); // ok
auto stk = std::stack<Simple,std::vector<std::reference_wrapper<Simple>>>(vr); // ok_2
smpl.txt.append("_append");
smpl_2.txt.append("_append_2");
smpl_3.txt.append("_append_3");
myStack.top().print(); // txt_append_3
myStack.pop();
myStack.top().print(); // txt_append_2
myStack.pop();
myStack.top().print(); // txt_append
return 0;
}
It compiles under gcc but does not under clang. The error says:
Error: stack:154:43: No type named 'type' in 'std::__1::enable_if'; 'enable_if' cannot be used to disable this declaration
Line in the stack file:

Maybe the reason is that you missed a constructor
template <typename T>
struct Stack : public std::stack<T,VecOfRef<T>>
{
Stack(VecOfRef<T>){}
};

You didn't add any constructors to your Stack class.
If you want to inherit std:stack's constructors, you must specify that, using:
using std::stack<T,VecOfRef<T>>::stack; in your class.

Related

vector of smart pointer of class template

I try to use a std::share_ptr to replace the pointer inside a traditional Node class.
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
template<class T>
class Node
{
public:
typedef std::shared_ptr< Node<T> > Ptr;
public:
T data;
std::vector< Node<T>::Ptr > childs;
};
int main()
{
return 0 ;
}
However, it states that the input of std::vector is not a valid template type argument.
So the question is; How to make the class work, if I want to use a smart pointer of template class as the argument of STL container.
The error messages are (VS 2015)
Error C2923 'std::vector': 'Node<T>::Ptr' is not a valid template type argument for parameter '_Ty'
Error C3203 'allocator': unspecialized class template can't be used as a template argument for template parameter '_Alloc', expected a real type
[Editor]
Add head include files, and make them run-able.
Add error message
Your code seems correct to me, at least it compiles (but does nothing) both on gcc and clang, no way to try vs2015 sorry, there is a chance that is not c++11 compliant?
Anyway here is a slightly expanded version of your code that do something (and shows how to use that shared_ptr you are trying to master):
#include <iostream>
#include <vector>
#include <algorithm>
#include <memory>
#include <sstream>
template<class T>
class Node
{
public:
typedef std::shared_ptr< Node<T> > Ptr;
T data;
std::vector< Ptr > childs;
void add_child(T data) {
auto p = std::make_shared<Node<T>>();
p->data = data;
childs.push_back(p);
}
std::string dump(int level = 0) {
std::ostringstream os;
for (int i = 0; i < level; ++i) os << '\t';
os << data << '\n';
for (auto &c: childs) os << c->dump(level + 1);
return os.str();
}
};
int main()
{
Node<int> test;
test.data = 1;
test.add_child(2);
test.add_child(3);
std::cout << test.dump();
return 0 ;
}

How to pretty print the name of a template parameter at compile time

The question is rather simple: how to pretty print the name of a template parameter in a C++ class and assign it to a class variable at compile time ?
It seems that both typeinfo (typeid) and boost::typeindex must be evaluated at runtime or as least some part of them. This apparently does not allow the compiler to completely solve a constexpr containing a call to one of this function.
template<typename T>
class X
{
public:
static const char * name = /* SOME C++ code transforming T in a string (either std::string or char */
};
What am I missing ?
Is it only possible to generate a name at runtime ? In that case, does I really need an instantiated object ? It doesn't seem right to me, because the following perfectly work without any instance:
#include <iostream>
#include <string>
#include <boost/type_index.hpp>
using namespace std;
template<class T>
class X
{
public:
static std::string name()
{
return boost::typeindex::type_id<T>().pretty_name();
}
};
struct foobar {};
int main()
{
cout << X<int>::name() << endl;
cout << X<foobar>::name()<< endl;
}
So instead of having name() as a class method, I'd like to have it as a class variable.
I think, it is possible to use custom Type Traits. Please see the next example:
#include <iostream>
#include <string>
using namespace std;
//Using stub type traits
template <class T>
struct TypeTraits;
//your TypeTraits for specific types...
template<>
struct TypeTraits<int>
{
constexpr static const char *name = "int";
};
template<class T>
class X
{
public:
constexpr static const char * name = TypeTraits<T>::name;
};
struct foobar {};
//TypeTraits for custom foobar
template<>
struct TypeTraits<foobar>
{
constexpr static const char *name = "foobar";
};
int main()
{
//Now you can use static member here
cout << X<int>::name << endl;
cout << X<foobar>::name<< endl;
}
Also TypeTraits can be used (and expanded) for other purposes.

Show most basic type declaration of nested typedefs in c++

When reading someone else's code, is there an easy way to unfold the underlying types of a nested typedef, except for going through all headers, searching for the respective definitions?
E.g. today I encountered
auto* p = new A<B::C>();
where B::C is defined in some header as
template <typename T>
class B: public BBase {
typedef B< D<E, E> > C;
}
and D and E are defined somewhere else. C
Can I somehow display that p is actually A<B<D<E, E>>>?
An alternative if you don't want to demangle typeid names is:
template<typename> struct TC;
Then put TC<A<B::C>> a; somewhere and you'll get a compiler error with the full deduced type in it.
For example:
template<typename> struct TC;
template<typename> using A = int;
using B = A<float>;
int main()
{
TC<B> a;
}
GCC outputs:
main.cpp:8:11: error: aggregate TC<int> a has incomplete type and cannot be defined
As you can see, B was substituted for A<float>, which was substituted for int in the compiler error.
You can use typeid(T).name(). It gives you a nice readable type declaration in Visual C++. With g++ compiler you have to use g++-specific functionality to demangle the somewhat cryptic result.
In order to use typeid you must include the <typeinfo> header.
The g++ name demangling function is abi::__cxa_demangle from the g++ <cxxabi.h> header.
Example (I had to fix various details of your alleged declarations):
template< class > struct A {};
template<class, class> struct D {};
struct E {};
struct BBase {};
template<class>
class B: public BBase
{
public:
using C = B< D<E, E> >;
};
#include <string>
#include <typeinfo>
using namespace std;
#ifdef __GNUC__
# include <cxxabi.h>
auto demangled( char const* name )
-> string
{
int status = 0;
char* realname = abi::__cxa_demangle( name, 0, 0, &status );
string result = realname;
free( realname );
return result;
}
#else
# include <sstream>
auto demangled( char const* name )
-> string
{
// Possibly remove all instances of "struct ", "class " and "enum "
return name;
}
#endif
#include <iostream>
auto main() -> int
{
auto* p = new A<B<int>::C>();
(void) p; // unused
cout << demangled( typeid( p ).name() ) << endl;
}
Output with g++:
A<B<D<E, E> > >*
An alternative is the trick presented by TartanLlama, of using the relevant type in an undefined template:
template<class> class Incomplete;
auto main() -> int
{
Incomplete< A<B<int>::C> > x;
}
which with g++ generates the error message:
ar.cpp:24:36: error: aggregate 'Incomplete<A<B<D<E, E> > > > x' has incomplete type and cannot be defined
Incomplete< A<B<int>::C> > x;
^
Those are the options that comes to my mind:
1) Debug printing, you can temporary add typeid(E) etc, but requires compiling and running, so not just reading the code.
2) Using an IDE like visual studio, qt creator etc, should be able to show you the actual typedefs/defines when hovering with the mouse on any usage of the typedef/defines.
3) Using text editors, many text editor might allow to have plugins to speed up the search and to jump from symbol to symbol to quickly find were they are defined.
So final answer I think by just looking at the code there is no way to know that, and that is actually a bit of a problem coming with the defines, it obfuscates the code a little.
on gcc/clang:
#include <iostream>
#include <cxxabi.h>
#include <string>
#include <stdexcept>
#include <exception>
#include <typeinfo>
std::string demangle(const char* mangled_name)
{
using namespace std;
size_t len = 0;
int stat = 0;
struct deleter {
void operator()(const char* p) const {
if (p) {
auto p1 = const_cast<char*>(p);
free(p1);
}
}
};
using ptr_type = std::unique_ptr<const char, deleter>;
auto pname = ptr_type(abi::__cxa_demangle(mangled_name,
nullptr,
&len,
&stat),
deleter());
if (stat)
{
switch(stat) {
case -1:
throw std::bad_alloc();
break;
case -2:
throw std::logic_error("invalid name: "s + mangled_name);
break;
case -3:
throw std::invalid_argument("demangle");
default:
throw std::logic_error("unknown error code "s + to_string(stat));
}
}
return string(pname.get(), len);
}
template<class X, class Y> struct D {};
struct E {};
template <typename T>
struct B {
typedef B< D<E, E> > C;
};
int main()
{
using namespace std;
cout << demangle(typeid(B<int>::C).name()) << endl;
return 0;
}
no doubt windows will have a similar means of detangling a name.
expected output:
B<D<E, E> >

C++ expected primary-expression compile error

#include <boost/format.hpp>
#include <boost/scoped_ptr.hpp>
#include <stdexcept>
#include <unordered_map>
#include <functional>
#define DECLARE_OBJECT(classname) namespace {core::declare_object<classname> __declarartion_#classname;}
namespace core {
class dungeon;
class object;
typedef std::function<object* (dungeon *)> object_creator;
namespace library_type {
enum type {
landscape = 0, walker, foe, bonus,object = 42
};
};
struct library_error : public std::logic_error
{
explicit library_error(const std::string &what) : std::logic_error(what) {};
};
template <enum library_type::type type>
class library {
public:
static library<type> *instance() {
if (!m_instance)
m_instance = new library<type>();
return m_instance;
}
template<typename T>
void add_object() {
boost::scoped_ptr<T> obj(T::create(nullptr));
m_library.insert(obj->name(), T::create);
}
const object_creator& get_object(const std::string &key) {
auto lookup_iterator = m_library.find(key);
if (lookup_iterator == m_library.end())
throw library_error(boost::format("Object creator for key `%1%' not found\n") % key);
return *lookup_iterator;
}
private:
library () {};
static library<type> *m_instance;
std::unordered_map<std::string, object_creator> m_library;
};
template <enum library_type::type type>
library<type>* library<type>::m_instance;
template <enum library_type::type type, typename T>
struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = instance->add_object<T>;
method();
}
};
};
int main()
{
}
Hello. This simple C++0x code gives me error in declare_object constructor
example.cpp: In constructor ‘core::declare_object<type, T>::declare_object()’:
example.cpp:52:43: error: expected primary-expression before ‘>’ token
example.cpp:52:44: error: expected primary-expression before ‘;’ token
I have really no idea where I am wrong. Maybe clear view and suggestions?
Sorry for long listing.
EDIT: Answer was auto method = instance -> template add_object<T>;. Why you deleted your answer?
To get a pointer to member function you need to follow the syntax in the other answer.
Since the member function is furthermore a template, you need to indicate this because it’s a dependent name:
auto method = &library_type<type>::template add_object<T>;
Otherwise C++ will parse the pointy braces in add_object<T> as less-than and greater-than operators.
struct declare_object
{
declare_object() {
auto instance = library<type>::instance();
auto method = &library<type>::template add_object<T>;
(instance->*method)();
}
};

Using boost::mpl, how can I get how many template classes are not "Empty", and call some macro with this number?

I want to call a macro with some arguments depending on the result of boost::mpl::eval_if (or a similar function) that could give how many template arguments are not empty. Say we have some pseudocode like the following:
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
eval_if<is_not_same<arg1, EmptyType>, FILL_MY_CLASS_DEFINE(1)> else
eval_if<is_not_same<arg2, EmptyType>, FILL_MY_CLASS_DEFINE(2)> else
eval_if<is_not_same<arg3, EmptyType>, FILL_MY_CLASS_DEFINE(3)>;
};
I am trying to fill my class with some content depending on how many arguments are EmptyType. I wonder how such thing can be done in C++03 via Boost.MPL/Preprocessor or some other Boost library?
You don't need preprocessor or mpl. Partial specialization is you need:
Edit This works in C++03, see it live: https://ideone.com/6MaHJ
#include <iostream>
#include <string>
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
// FILL_MY_CLASS_DEFINE(3)
};
template<class arg1, class arg2>
class my_class<arg1,arg2,EmptyType>
{
// FILL_MY_CLASS_DEFINE(2)
};
template<class arg1>
class my_class<arg1,EmptyType,EmptyType>
{
// FILL_MY_CLASS_DEFINE(1)
};
template<>
class my_class<EmptyType,EmptyType,EmptyType>
{
// FILL_MY_CLASS_DEFINE(0)
};
int main(int argc, const char *argv[])
{
my_class<std::string, double, int> a;
my_class<std::string, int> b;
my_class<void> c;
return 0;
}
Are you looking for variadic templates?
#include <tuple>
#include <iostream>
#include <string>
template <typename... Arg>
struct my_class
{
// getting the size of the argument list:
enum { size = sizeof...(Arg) }; // in absense of static fields with initializers...
// demo filling the struct with data:
std::tuple<Arg...> arg_data;
my_class(Arg&&... a) : arg_data(std::forward<Arg>(a)...) { }
};
int main(int argc, const char *argv[])
{
my_class<std::string, int> a("hello world", 42);
std::cout << "size: " << a.size << std::endl;
std::cout << "last: " << std::get<a.size-1>(a.arg_data) << std::endl;
return 0;
}
Output:
size: 2
last: 42
When you have many template arguments, a partial specialization can be impractical and error-prone.
The code below will do what you want, but as it was already mentioned in other answers, it's not always the best way to proceed.
#include <boost/mpl/count_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::is_same;
using boost::mpl::_;
using boost::mpl::not_;
using boost::mpl::count_if;
#define FILL_MY_CLASS_DEFINE(x) static const int __x__ = x // an example, watch out: no semicolon at the end
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
// count the types which are not equal to EmptyType
static const long NonEmptyCount = count_if<type, not_<is_same<_, EmptyType> > >::value;
// invoke a macro with an argument
FILL_MY_CLASS_DEFINE(NonEmptyCount);
};