This question already has an answer here:
Why C++ containers don't allow incomplete types?
(1 answer)
Closed 6 years ago.
It seems that std::deque does not allow to use it in a recursive way with clang on osx when not using libstdc++ (10.9+ target)
#include <deque>
struct node { std::deque<node> childs; };
int main() {
node n;
}
This simple code compile with clang only if I set MACOS_DEPLOYMENT_TARGET=10.8 (because the clang compiler links with libstdc++) but it gives a lot of errors if I try to compile with libc++ (default c++ target on 10.9+), while with gcc 4/5 it works without problems...
It's a compiler bug or the standard does not allow this? It's seems a quite obvious use of a container...
In general, you should not expect this code to compile. To be sure that it compiles with any standard-compliant compiler you must use an extra level of indirection in one of the following or similar ways:
struct node { std::deque<node> *children; };
struct node { std::unique_ptr<std::deque<node>> children; };
struct node { std::deque<node*> children; };
Related
This question already has an answer here:
Template class compiles with C++17 but not with C++20 if unused function can't be compiled
(1 answer)
Closed 8 months ago.
We came an interesting case where MSVC doesn't check namespace resolution for unused functions in a templated class. For example:
#include <string>
namespace
{
template<class Iterator>
struct Foo
{
Foo()
{
}
void parse(Iterator begin, Iterator end)
{
foo::string a(begin, end - begin);
}
};
}
using CharFoo = Foo<const char *>;
CharFoo fooParser;
int main()
{
}
This compiles and runs just fine in MSVC, but gcc and clang both give an error. Is this an MSVC bug technically? Does the C++ standard say anything about this case as to whether or not this is an error?
In general MSVC does NOT compile any template functions if they are not used at all. Most compilers differ in that point -- they always check the code (where I do not know what the C++ standard says.)
This question already has an answer here:
get<string> for variants fail under clang++ but not g++
(1 answer)
Closed 4 years ago.
The following uses of std::visit compiles properly under gcc 7.2 but fails to compile under clang 5.0. Does anyone know what the problem is?
#include <variant>
struct S1 {int foo() { return 0; }};
struct S2 {int foo() { return 1; }};
using V = std::variant<S1, S2>;
int bar() {
V v;
return std::visit([](auto& s) { return s.foo(); }, v);
}
The first error is this:
include/c++/7.2.0/variant:238:46: error: cannot cast 'std::variant<S1, S2>' to its private base class
'std::__detail::__variant::_Variant_storage<true, S1, S2>'
return __get(std::in_place_index<_Np>, std::forward<_Variant>(__v)._M_u);
Here is a link to godbolt shows this error: https://godbolt.org/g/5iaKUm
This is known bug 33222 that seems to only affect libstdc++'s std::variant (and other constructs using the same combination). The problem is related to friend function to templates - see the thread for more detail.
The variant from libc++ doesn't seem to use the technique of friends that libstdc++ used, so you might want to temporarily change to libc++ in the meantime.
Small update: This has been fixed in the latest trunk.
As this website shows, following code will not be supported in Clang using C++11:
class Node {
vertex<Node> children;
};
An error will occur:
field has incomplete type 'Node'
But such code is supported in C++98 and other compilers such as gcc in C++11.
I know I can use
vertex<Node*>
instead, but at present I have some incompatibility issue with old code in C++98.
My question is, (1) can I compile such code using Clang in C++11? (2) I think a tree structure does inevitably need definition like above, without support of such feature, how can I realize such tree structure?
update:
Sorry for forgetting to give definition of vertex, What about the following code:
class Node {
vector<Node> children;
};
Just change vertex into a container vector. It is not valid in Clang with C++11, but ok with other compilers and with C++98.
update again:
It seems vector works OK..but list fails
class Node {
std::list<Node> children;
};
update again:
Following is my code:
#include <list>
using namespace std;
class Node {
list<Node> nodes;
};
int main(int argc, char const *argv[])
{
return 0;
}
or simpler:
#include <list>
class Node {
std::list<Node> nodes;
};
int main() {}
I'm using Clang 4.0 and using the following command to compile:
clang++ -std=c++11 -stdlib=libc++ test.cpp
The error is
/usr/bin/../lib/c++/v1/list:212:9: error: field has incomplete type 'Node'
If it does not compile, it means that vertex attempts to use Node in a way that requires it to be completely defined. Most of the time, this implies (for generic code) using the size of the T parameter:
either explicitly (sizeof(T))
or implicitly template <typename T> struct vertex { T data[3]; }; is using the size of T to compute the layout of the type
Another (possible) issue, is relying on methods of T for some template instantiation; however this is much rarer.
You can avoid this requirement by changing the definition of vertex. Not knowing what it is though, we won't be able to get much more specific...
This compiles in Visual C++ 2010.
It does not compile und MINGW.
struct nextifcondinfo
{
hash_map <string, nextifcondinfo> next;
int action;
};
I get an error message:
Description Resource Path Location Type
forward declaration of 'struct nextifcondinfo' C/C++ Problem
Can you tell me what switches to use in mingw to solve? Or do you have any other ideas?
I don't believe your code is supposed to compile but it does depend on the hash_map implementation. Looks like you've been lucky with VC++ and unlucky with MinGW.
To solve use pointers, for instance
struct nextifcondinfo
{
hash_map <string, nextifcondinfo*> next;
int action;
};
You could use smart pointers as well.
My question is related to Prasoon's question about non POD types and value initialization.
I tried the following code on online compilers like Ideone and Codepad but the executables gave runtime error on both the sites.
#include <iostream>
#include <cassert>
struct Struct {
std::string String;
int Int;
bool k;
};
struct InStruct:Struct
{
InStruct():Struct(){}
};
int main()
{
InStruct i;
assert ( i.Int == 0);
std::cout << "Hello";
}
Ideone Output here
Codepad Output here
Does that mean neither of them support C++03 value initialization feature?
Does that mean neither of them support C++03 value initialization feature?
Yes.
Prior to version 4.4, GCC did not completely support value initialization (the Boost GCC compatibility header explains this and has links to the relevant GCC defect reports; see line 77).
If your code needs to be portable, you should be very careful relying on value initialization; GCC did not support it fully until recently and Visual C++ does not fully support it even in its latest version, Visual C++ 2010.
The declaration
InStruct i;
does not invoke value initialization
$8.5.3/10 - "An object whose
initializer is an empty set of
parentheses, i.e., (), shall be
value-initialized."
If you want to value-initialize, you would require an expression something like
assert(InStruct().Int == 0);
Try it now! - Ideone supports GCC-4.5.1