Or at least I think it is.
Consider the following code
#include <iostream>
#include <memory>
struct BaseBase {
virtual void foo() = 0;
virtual ~BaseBase(){}
};
template <typename Derived>
struct Base : BaseBase{
void foo() override{
static_cast<Derived*>(this)->foo();
}
};
struct D1 : Base<D1> {};
struct Unrelated {};
// no runtime polymorphism
template <typename SDerived>
struct SBase{
void foo() {
static_cast<SDerived*>(this)->foo();
}
};
struct SD1 : SBase<SD1> {};
template <typename T, typename ...Args>
void doFoo(Args&&... args){
T* t = new T(std::forward<Args>(args)...);
t->foo();
}
int main(){
doFoo<Unrelated>(); //compile time error, foo not found in unrelated
doFoo<SD1>(); //runtime crash
doFoo<D1>(); //runtime crash
return 0;
}
I was hoping the compiler would be nice enough to check for the existence of fooat compile time in doFoo but in both cases, with virtual in base, and without virtual in base the code compiles just fine but crashes at runtime.
Why is this?
Edit: clang setup
clang version 4.0.1 (tags/RELEASE_401/final)
Target: x86_64-unknown-linux-gnu
with doFoo<Unrelated>() commented out compiles.
and g++ setup
gcc version 7.1.1 20170630 (GCC)
compiles with doFoo<Unrelated>() commented out.
This is because both of the classes have a function called foo. It's present in the base class for each class.
However, all that function does is call itself, which will eventually result in a stack overflow.
Related
When is it possible to elide types of temporaries passed into a variadic function template? Overload resolution doesn't seem to work. Consider this:
#include <vector>
struct option
{
std::vector<int> to_wait;
std::vector<int> to_set;
};
namespace fsm
{
template <typename... Ts>
void generic_wait(Ts... Args) {
std::array<option, sizeof...(Ts)> hello = {{Args...}};
}
}
int main()
{
fsm::generic_wait(option{{2}, {3}}); // <-- This compiles
// fsm::generic_wait({{2}, {3}}); // <-- This I would like to compile
}
This compiles only when I directly specify the temporary type. If I leave it off it stops working (C++11). Can I do something to make it work?
Is there any way to construct this code so that I do not have to specify the template parameter of bar?
i.e. it does not currently compile, but will compile if I change bar(v) to bar<int>(v) in main.
#include <cstdlib>
#include <vector>
template <class T>
struct foo
{
foo(std::vector<T>& v)
{
}
};
template <class T>
void bar(const foo<T>& f)
{
}
int main()
{
std::vector<int> v;
bar(v); // does not compile
bar<int>(v); // compiles but is undesirable
return EXIT_SUCCESS;
}
The compiler is only allowed one implicit conversion but you can add an overload for bar that tries to convert whatever you give it to a foo and then calls your original bar with the temporary foo (which is what would happen if two implicit conversions was allowed in your original code):
template<typename T>
void bar(T& v) {
return bar(foo(v));
}
Since the conversion constructor in foo doesn't take the argument by const&, neither can this bar overload.
i trying to develop a Finite State Machine with template meta programming techniques, but i getting stuck with a map that it has to be fill at compile time, this the code(gcc 4.8 c++11):
#include <functional>
#include <type_traits>
#include <iostream>
#include <unordered_map>
namespace NSStateMachine {
//Definicion de estado unidad
template<class FSM, class From, class Event, class TO, bool(FSM::* transicion_fn)(const Event &)>
struct Transition
{
using FSM_TYPE=FSM;
using FROM_STATE= From;
using EVENT_TYPE= Event;
using TO_STATE_TYPE=TO;
using EVENT_BASE_TYPE = typename Event::BASE_TYPE;
static bool do_transition(FSM_TYPE& currenState, EVENT_BASE_TYPE const& aEvent)
{
return (currenState.*transicion_fn)(static_cast<EVENT_TYPE const&>(aEvent));
}
};
//States
template<class Transition, const Transition * const TransitionPtr, class ... Args>
class StateMachine
{
public:
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
{}
template<class Event>
bool evalEvent(const Event & aEvent)
{
std::cout<<"evento recibido"<<std::endl;
}
std::unordered_map<typename Transition::TransitionID, const Transition * const > transitionMap ;
};
}
int main()
{
//it doesnt compile, i canoot create the state machine
return 0;
}
The compile error:
error: 'TransitionPtr' is not a class, namespace, or enumeration
StateMachine():transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
^
The problem seem to be in the line
transitionMap{{static_cast<typename Transition::TransitionID>(*TransitionPtr::TransitionID_Value),nullptr}}
i will try to init the unorderer_map with the automatic constructor.
i have defined this Transition::TransitionID as a class variable defined in the class represented by the template argument
I will really appreciate any help.
Thx!!!!
i have already test with default types , it compile and work this
The error message is pretty clear. TransitionPtr is a pointer, not a type, so you can't use it to the left of :: in TransitionPtr::TransitionID_Value.
Also, I don't think you'll find a way to initialize an unordered_set at compile time, since it doesn't have constexpr constructors and in general almost certainly uses heap allocations.
g++ 5.2.1 fails to compile when it encounters a private method's address in a template deduction context whereas clang 3.5 only discards the specialization.
g++ 5.2.1 can access protected members of parents/friends in a class template parameter list when clang 3.5 sometimes fail to do so.
Which are wrong in which cases?
More precisely:
Should the compiler cause a hard error when trying to access a non accessible protected/private member in a template deduction context? Am I doing something wrong in my first example?
If not, should the compiler discard a specialization when trying to access (in a template deduction context) a protected member owned by:
a base class of this specific specialization
a class which declared this specific instantiation as a friend
a friend class which declared any instantiation of this template as a friend
The first question seems to have already been answered here (and the answer seems to be "no, the code isn't ill-formed and the compiler should simply discard this specialization"). However, since it's a prerequisite to the second question (and g++ 5.2.1 doesn't seem to agree), I want to be absolutely sure that it's g++ 5.2.1 which is wrong, not me.
Longer version with examples
I would like to make traits able to detect whether some functions/methods are implemented, even if they are protected members of some class (if you find this odd, I'll explain why I want to do this at the end of this question so that you can tell me I'm completely wrong, should learn how to design my classes, and maybe suggest me a cleaner way to do so).
My problem is that each of my attempts fail on either clang or g++ (oddly enough, not both at the same time): Sometimes it compiles but don't provide the expected result, sometimes it doesn't compile at all.
Even though it seems it isn't practical, I at least want to know when the compilers are faulty, and when I'm writing ill-formed code. Hence this question.
I use the C++11 dialect, and my clang version is actually the compiler provided with XCode 5 i.e. Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn).
To better illustrate what my problem is, here is a minimal exemple where clang compiles but g++ 5.2.1 doesn't:
#include <iostream>
#include <type_traits>
#include <utility>
struct PrivateFoo {
private:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
template<class C, class = void>
struct has_foo : std::false_type {};
template<class C>
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
std::true_type {};
int main() {
std::cout << std::boolalpha;
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
return 0;
}
output with clang 3.5:
PrivateFoo has foo: false
g++ 5.2.1 errors:
access_traits.cpp : [in instantiation of] ‘struct has_foo<PrivateFoo>’ :
access_traits.cpp:37:61: required from here
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp:7:8: [error]: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:32:56: [error]: [in context]
struct has_foo<C, void_t<check_signature<void(C::*)(), &C::foo>>> :
^
access_traits.cpp: [in function] ‘int main()’:
access_traits.cpp:7:8: erreur: ‘void PrivateFoo::foo()’ is private
void foo() {}
^
access_traits.cpp:37:42: [error]: [in context]
std::cout << "PrivateFoo has foo: " << has_foo<PrivateFoo>::value << '\n';
(text in brackets is translated, it was originally in my native language)
Here is an example where both compile but disagree on whether foo is accessible or not:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class = void>
struct has_foo_helper : std::false_type {};
template<class C>
struct has_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: false
output with g++ 5.2.1:
ProtectedFoo has foo: true
and finally here is an example where both compile and agree that they should be able to access foo:
#include <iostream>
#include <type_traits>
#include <utility>
struct ProtectedFoo {
protected:
void foo() {}
};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
}
template<class C>
struct has_public_or_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_public_or_protected_foo<C>>::value;
};
int main() {
std::cout << std::boolalpha;
std::cout << "ProtectedFoo has foo: ";
std::cout << has_public_or_protected_foo<ProtectedFoo>::value << '\n';
return 0;
}
output with clang 3.5:
ProtectedFoo has foo: true
output with g++ 5.2.1:
ProtectedFoo has foo: true
Also here is a more complete example which summarizes it all:
#include <iostream>
#include <type_traits>
#include <utility>
/* test classes */
struct PublicFoo {
void foo() {}
};
struct ProtectedFoo {
protected:
void foo() {}
};
struct PrivateFoo {
private:
void foo() {}
};
struct NoFoo {};
/* utilities */
// reimplement C++17's std::void_t
template<class...>
struct void_type {
typedef void type;
};
template<class... T>
using void_t = typename void_type<T...>::type;
// dummy class used to check whether a pointer to (possibly member) function
// exists with the good signature
template<class T, T>
struct check_signature {};
/* traits */
namespace detail {
template<class C, class D, class = void>
struct has_foo_helper : std::false_type {};
template<class C, class D>
struct has_foo_helper<C, D, void_t<check_signature<void(C::*)(), &D::foo>>> :
std::true_type {};
template<class C, class = void>
struct may_call_foo_helper : std::false_type {};
template<class C>
struct may_call_foo_helper<C, void_t<decltype(std::declval<C>().foo())>> :
std::true_type {};
}
template<class C>
struct has_foo : detail::has_foo_helper<C, C> {};
template<class C>
struct may_call_foo : detail::may_call_foo_helper<C> {};
template<class C>
struct has_protected_foo : protected C {
template<class, class, class>
friend class detail::has_foo_helper;
static constexpr bool value =
detail::has_foo_helper<C, has_protected_foo<C>>::value;
};
template<class C>
struct may_call_protected_foo : protected C {
template<class, class>
friend class detail::may_call_foo_helper;
static constexpr bool value =
detail::may_call_foo_helper<may_call_protected_foo<C>>::value;
};
/* test */
template<class T>
void print_info(const char* classname) {
std::cout << classname << "...\n";
// comment this if you want to compile with g++
//*
std::cout << "has a public method \"void foo()\": ";
std::cout << has_foo<T>::value << '\n';
std::cout << "has a public or protected method \"void foo()\": ";
std::cout << has_protected_foo<T>::value << '\n';
//*/
std::cout << "has a public method \"foo\" callable without any arguments: ";
std::cout << may_call_foo<T>::value << '\n';
std::cout << "has a public or protected method \"foo\" callable without any "
"arguments: ";
std::cout << may_call_protected_foo<T>::value << '\n';
std::cout << '\n';
}
int main() {
std::cout << std::boolalpha;
// both g++ 5.2.1 and clang 3.5 compile
print_info<PublicFoo>("PublicFoo");
// g++ 5.2.1 fails to compile has_foo, clang 3.5 compiles fine
print_info<ProtectedFoo>("ProtectedFoo");
// g++ 5.2.1 fails to compile, clang 3.5 compiles fine
print_info<PrivateFoo>("PrivateFoo");
// both g++ 5.2.1 and clang 3.5 compile
print_info<NoFoo>("NoFoo");
return 0;
}
Why do I want to do this?
Skip this if you don't want to know the details. I just wrote this in case you were either shocked by the idea of me trying to detect protected members and/or curious about why I asked this question.
I was writing some kind of iterator template classes built out of other iterators and I got tired of writing multiple specializations depending on whether these iterators meet some requirements (ForwardIterator, BidirectionalIterator, RandomAccessIterator... although my iterators actually meet some relaxed versions of these concepts, they are kind of "proxy iterators" but it's not really relevant here).
For instance, if I only use random access iterators, my new custom iterator could (and should) also be some kind of random access iterator, hence implement operator+=, operator+, operator-=, operator-, operator<, operator>, operator<= and operator>=. However, some of these operators can easily be deduced from others, and they should only be defined if all the iterator I use are random access iterators.
I finally thought I'd just make something to provide default implementations if available. However, I wasn't really fond of the std::allocator_traits way as it wouldn't be very handy and readable with iterators (plus, I wouldn't be able to use them with some standard utilities).
The design I finally choose consists in having a template class which will build a full-fledged iterator out of a minimal implementation (for instance containing only the operator+=, operator==, operator* and operator> definitions) by having an inheritance chain of "mixins" (whose ancestor is my minimal iterator) detecting whether the functions/methods they need are available in their base class and defining the default methods if they are.
There is a subtility though. Sometimes I want to return a reference to the final iterator (for instance in Iterator& operator++()). If it's a method I redefine, I can easily solve that with CRTP and a static_cast, but what if my mixins don't touch that method at all?
I figured I should probably forbid the use of any method I haven't touched and inherit my minimal iterator with the protected access specifier... but now then my traits fail to detect the availability of some protected methods.
Therefore, I'd like to have traits able to detect whether some members are available with either public or protected visibility.
In MSVC 2008, I have the following code:
class Foo {
// Be a little smarter about deriving the vertex type, to save the user some typing.
template<typename Vertex> inline void drawVertices(
Elements vCount, RenPrim primitiveType, PixMaterial *mtl, Vertex const *vertices)
{
this->drawVertices(vCount, primitiveType, mtl, vertices, Vertex::VertexType);
}
virtual void drawVertices(
Elements vCount,
RenPrim primitiveType,
PixMaterial *mtl,
void const *vertices,
uint vertexType) = 0;
};
I use it something like:
struct RenFlexibleVertexPc
{
enum { VertexType = RenVbufVertexComponentsPc };
float x;
float y;
float z;
GraVideoRgba8 c; // Video format, not external!
};
PixMaterial *material;
struct Pc : RenFlexibleVertexPc
{
void set(Triple t, uint cl) { x = (float)t.x_; y = (float)t.y_; z = (float)t.z_; c = cl; }
} vpc[4];
...
Foo *renderer;
renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);
This works fine in MSVC 2008 SP1. However, GCC (3.4 and 4.1,2) throws a "no matching function for call to function" error, apparently not seeing the template when there is a non-template function with more arguments.
Is GCC broken, or is my code broken, and if so, why?
There is no problem with overloading or inheritance:
#include <iostream>
#include <memory>
namespace {
struct A {
virtual void f()
{
std::cout<<"inside A's f()\n";
}
template <typename T> void f(T t)
{
std::cout<<T::i<<'\t';
this->f();
}
};
struct B : A {
void f()
{
std::cout<<"hello\t";
A::f();
}
};
struct C {
static const unsigned int i = 5;
};
struct D {
enum { i = 6 };
};
}
int main()
{
std::auto_ptr<A> b(new B());
b->f(C());
b->f(D());
}
Works correctly. On the other hand, the smallest example I can find that exhibits your problem does not have inheritance or overloading:
#include <iostream>
namespace {
struct A {
template<class C> void print(C c)
{
c.print();
}
};
}
int main()
{
struct B {
void print()
{
std::cout << "whee!\n";
}
};
A a;
B b;
a.print(b);
}
Note that if struct B is defined in a namespace (whether it's an unnamed namespace, or a completely different namespace, or the global namespace) instead of inside main() that this compiles without error.
I don't know enough of the standard to say if this is a bug, but it appears to be one. I've gone ahead and reported it to the GCC bug database.
And here's your answer from the GCC developers (from the link above): "Local classes cannot be template arguments."
So the code is broken. Not that it's a bad idea. In fact, C++0x removes this restriction.
I noticed the line
Note that the code works in GCC if I explicitly cast vpc to (RenFlexibleVertexPc *)
And since RenFlexibleVertexPc is not a local class this makes sense. However Pc is a local class/struct, so it is not allowed.
#OP: Specifying the template parameter is a valid approach.
renderer->drawVertices<RenFlexibleVertexPc>(4, RenPrimTriangleFan, material, vpc);
With Pete's additions, you code also compiles on Apple's GCC 4.0.1, so I suspect there's something your posted code is missing that's causing the problem.
#Max: GCC's treatment of your source is standard. Struct B is local to main(), so B (and thus main()::B::print()) is not visible outside main(). As you're probably aware, moving the definition of B outside of main() and it will compile.
The definition of VertexType is already in the code (an enum). Elements is an unsigned long. Note that the code works in GCC if I explicitly cast vpc to (RenFlexibleVertexPc *)
If it's an enum why pass an object of type array 4 of struct? What is RenFlexibleVertexPc? The last argument to drawVertices should either be a constant pointer to a Vertex object or a const* to an object of a class derived from Vertex.
Foo *renderer;
renderer->drawVertices(4, RenPrimTriangleFan, material, vpc);
You are calling a function on an uninitialized pointer. I hope this is not the real code. \