Understanding templates defined inside templates (C++) - c++

According to my understanding, the following two programs should be effectively identical, but the second fails to compile. Note that in this simplified example, the nesting is obviously useless, but it's necessary in the original context.
Version 1: works as expected
#include <iostream>
template<typename Value>
struct Anything {
Value value;
};
using A = const char *;
template<template<typename> class B>
struct Inner {
template<typename C>
using type = B<C>;
};
template<template<typename> class B>
struct OuterBase {
B<A> b;
void
print() { std::cout << "b: " << b.value << std::endl; }
};
using Outer = OuterBase<Inner<Anything>::type>; // this version works
int
main()
{
Outer outer;
outer.b.value = "foo";
outer.print();
return 0;
}
The compiler error in this version is "expected a template, got TypeBox<A>::Inner<Anything>::type".
Version 2: fails with compile error
#include <iostream>
template<typename Value>
struct Anything {
Value value;
};
template<typename A>
struct TypeBox {
template<template<typename> class B>
struct Inner {
template<typename C>
using type = B<C>;
};
template<template<typename> class B>
struct OuterBase {
B<A> b;
void
print() { std::cout << "b: " << b.value << std::endl; }
};
using Outer = OuterBase<Inner<Anything>::type>; // compile error here
};
int
main()
{
using Box = typename TypeBox<const char *>::Outer;
Box box;
box.b.value = "foo";
box.print();
return 0;
}
I would expect the TypeBox struct to be transparent when resolving the types inside, but according to gcc 12.2.1, it isn't. Why not?

The difference in your second example is that a compiler cannot verify at the point of definition of the template that Inner<Anything>::type is really a class template or alias template. The problem is that Inner is a nested class template and you could in theory partially or explicitly specialize Inner for the given template argument later, so that type names e.g. a type.
So compilers tend to require that you place the template keyword before the template's name in such a case to state that it really is a template:
using Outer = OuterBase<Inner<Anything>::template type>;
My understanding is that technically there is nothing in the standard requiring this use of template though, but that this wasn't entirely clear. However, the standard did allow using the template keyword in this position, but will deprecate this allowance with C++23. If I am not mistaken compilers should also allow this without template keyword in the future even for previous standard revisions (as defect report). There wasn't ever really a point in performing this test.
See also CWG issue 1478 and the paper proposing the deprecation P1787R6.

Related

Wrong output for SFINAE member detect in MSVC2015

I was learning about SFINAE and how to easy implement it with void_t. But I get different output for different compilers:
//pre c++17 void_t definition:
template<class... Ts> struct make_void {typedef void type;};
template<class... Ts> using void_t = typename make_void<Ts...>::type;
//check for member helper structures
template<class, class = void>
struct has_abc : std::false_type
{ };
template<class T>
struct has_abc<T, void_t<decltype(T::abc)>> : std::true_type
{ };
class has
{
public:
void abc();
};
class has_not
{ };
int main()
{
std::cout << has_abc<has>::value << std::endl;
std::cout << has_abc<has_not>::value << std::endl;
}
GCC 5.3.0 prints expected output 1 0, but MSVC 2015 prints 0 0, why?
EDIT:
Additional example with working GCC 5.3.0 code that supposedly violates c++ syntax:
template<class T>
void test()
{
std::cout << std::is_same<decltype(T::func), void(T::*)(void)>::value << std::endl;
}
class Test
{
public:
void func();
};
int main()
{
test<Test>();
}
Output:
1
In fact there is an error with your code. MSVC is right while GCC is simply wrong.
The syntax for pointer to member function doesn't work like that. You have to put the & in front of the expression:
//check for member helper structures
template<class, class = void>
struct has_abc : std::false_type {};
template<class T>
struct has_abc<T, void_t<decltype(&T::abc)>> : std::true_type {};
// Notice the '&' there ------^
The syntax for T::member only work with static data member, and typename T::member work for member types. While working with sfinae, it's important to distinguish small syntax properties and differences.
As a request in the comment, here's multiple statement that shows that non static member cannot be referenced without the & with GCC 5.3: https://godbolt.org/g/SwmtG2
Here's an example with GCC: http://coliru.stacked-crooked.com/a/0ee57c2c34b32753
Here's an example with MSVC: http://rextester.com/FJH22266
Here's the section from the C++ standard that explicitly state that without the &, the expression is not well formed:
[expr.prim.id]/2
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
as part of a class member access ([expr.ref]) in which the object expression refers to the member's class or a class derived from that class,
or to form a pointer to member ([expr.unary.op]), or
if that id-expression denotes a non-static data member and it appears in an unevaluated operand. [ Example:
-
struct S {
int m;
};
int i = sizeof(S::m); // OK
int j = sizeof(S::m + 42); // OK
— end example ]
As we discussed in the chat, we concluded that the reason there is a difference with the two compilers is that both GCC and MSVC has bugs that prevent this code to work well. As mentionned, MSVC will refuse to apply the SFINAE rule if there is an unrelated class that don't implement the rule correctly: http://rextester.com/FGLF68000
Note that sometime, changing the name of a type trait helped MSVC to parse my code correctly, but it's mostly unreliable.
Consider reporting a bug to microsoft and upgrade your GCC version if you want your code to work as expected.
this way works:
template<class T>
struct has_abc<T, void_t<decltype(std::declval<T>().abc())>> : std::true_type
{ };

C++ template for variable type declaration

I have a number of classes with differing members, all of which have operations of the following type
::basedata::Maindata maindata;
::basedata::Subdata subinfo("This goes into the subinfo vector");
subinfo.contexts(contextInfo);
maindata.subdata().push_back(subinfo);
Note that I am asking how to set up generalized templates to perform these actions. I cannot set up a special case for each type of maindata and subinfo. I also need to be able to see how to call the template from my main code. I have been able to set up a template if maindata.subdata() exists, but keep getting a compilation failure on a call to the template if it does not exist. That is create the template of the form
perform_Push(maindata.subdata(), subinfo);
so that it can be compiled whether or not maindata.subdata() exists or not.
I could accept templates that build so that the main code can show
bool retval
retval = hasmember(maindata, subdata);
if (retval)
{
buildmember(maindata.subdata, subinfo);
setAttributes(subinfo, data);
perform_Push(maindata.subdata(), subinfo)
}
else
{
// Perform alternate processing
}
As of now, the code inside the if would not compile when the templates being called should just be void.
While ::basedata::Maindata is always defined, ::basedata::Subdata may or may not be defined depending on the release of libraries that my code is being build with. subdata is defined as a vector belonging to maindata which therefore has the push_back() operation defined. There are too many types of subData to create a separate template for each type as T::Subdata within a template in any case.
That is, if subdata was the only case, I could create a specialization of the template T as ::maindata::subdata and a generic Template T.
I do not have any control of the include files or library that for this so that I cannot create a #define of a variable to test with the pre-compiler. Is there a good way of setting up a template that would allow this to work? I could use a template that returns a boolean true (success) or false (no such definition) and call the alternate processing at run time. I would not need to have an alternate template.
Basically, I am asking how to apply SFINAE to this particular situation.
I have managed to figure out what I need to do to set up the basic template
If I have the most basic operation
maindata.subdata().push_back(data)
I can define a template of the form,
<template class T, typename D>
auto doPush(D data) -> decltype(T.pushback(data), void())
{
T.push_back(data);
}
and the call would be
doPush<maindata.subdata()>(data);
However, the problem would be how to set it up when maindata does not yet have a member subdata.
You can use this templates to obtain a boolean value that tell you if exist member type Subdata in a generic type T. This works only if T is a struct/class not a namespace.
#include <type_traits>
template <class T, class V = void>
struct hasSubdata
{
enum { value = false };
};
template <class T>
struct hasSubdata<T, typename std::enable_if< std::is_same<typename T::Subdata, typename T::Subdata>::value >::type>
{
enum { value = true };
};
struct basedata1
{
struct Subdata {};
};
struct basedata2
{
};
#include <iostream>
int main ()
{
std::cout << "basedata1: " << hasSubdata<basedata1>::value << std::endl;
std::cout << "basedata2: " << hasSubdata<basedata2>::value << std::endl;
}
But you can't use a normal if because the compiler checks the correctness of all the possibilities.
You have to act in a similar way (pretty ugly):
template <class T, bool = hasSubdata<T>::value>
struct SubdataUser
{
static void foo ()
{
std::cout << "I can use SubData member :)" << std::endl;
typename T::Subdata subinfo ();
}
};
template <class T>
struct SubdataUser<T, false>
{
static void foo ()
{
std::cout << "I can not :(" << std::endl;
}
};
int main ()
{
SubdataUser<basedata1>::foo ();
return 0;
}
Unfortunately to my knowledge, you can not have a template hasMember<Type,Member>::value because if Member does not exist, compilation fails.
But you might like a solution of this type
#include <type_traits>
#include <iostream>
struct basedata1
{
struct Subdata1 {};
struct Subdata2 {};
struct Subdata3 {};
};
struct basedata2
{
struct Subdata1 {};
//struct Subdata2 {};
struct Subdata3 {};
};
template <class...>
struct Require
{
enum { value = true };
};
template <class T, bool = true>
struct Impl
{
static void foo ()
{
std::cout << "At least one of the members required is not available :(" << std::endl;
}
};
template <class T>
struct Impl<T, Require< typename T::Subdata1,
typename T::Subdata2,
typename T::Subdata3 >::value >
{
static void foo ()
{
std::cout << "All members are available :)" << std::endl;
typename T::Subdata2 my_var;
}
};
int main( int argc, char* argv[] )
{
Impl<basedata1>::foo ();
Impl<basedata2>::foo ();
return 0;
}
I hope this helps
I have managed to figure out what I need to do to set up the basic template as well as the member template. It is actually two different questions and two different answer templates. It requires a basic generic template called by a specific member template.
C++ preprocessor test if class member exists

Why is template disambiguator needed in this case?

I'm trying to understand why I need to use a template disambiguator in some openCL code.
EDIT: Here's a minimal reproducing case:
//test.hpp
#include <iostream>
#include <vector>
#include "cl.hpp"
template <typename T>
class Foo {
public:
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
Foo();
void bar();
};
template<typename T>
Foo<T>::Foo() {
cl::Platform::get(&platforms);
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
}
template<typename T>
void Foo<T>::bar() {
// Fails to compile: error: expected expression
//std::cout << devices[0].getInfo<CL_DEVICE_NAME>() << std::endl;
// Works
std::cout << devices[0].template getInfo<CL_DEVICE_NAME>() << std::endl;
// Also works
cl::Device &mydevice = devices[0];
std::cout << mydevice.getInfo<CL_DEVICE_NAME>() << std::endl;
}
and the source file:
//test.cpp
#include "test.hpp"
int main() {
Foo<double> foo = Foo<double>();
foo.bar();
return 0;
}
What is different about the reference that makes a template disambiguator unnecessary? I"m trying to understand where the ambiguity is here. (Also, I know I'm not using the templated variable in my class, this is just a minimal case that reproduced the issue.)
First of all, this is just a typical issue in general in template code. The issue is that because, at the point of parsing the nature of getInfo is unknown (is it a function template or a regular member variable ?) the parser does not know whether to interpret < as less-than or as the start of specifying template parameters.
Thus the rule in §14.2 [temp.names]/4, of which the example is:
template<class T> void f(T* p) {
T* p1 = p->alloc<200>(); // ill-formed: < means less than
T* p2 = p->template alloc<200>(); // OK: < starts template argument list
T::adjust<100>(); // ill-formed: < means less than
T::template adjust<100>(); // OK: < starts template argument list
}
Now, in your case this seems a bit silly I fathom, because it's a Device right ? Yes, in your case. But what of:
template <typename T> struct Wrecker { using type = std::vector<Device>; };
template <> struct Wrecker<double> { using type = std::vector<Other>; };
template <typename T>
struct Foo {
using Devices = typename Wrecker<T>::type;
Devices devices;
void bar();
};
So, yes, the rule is not as precise as it could be. It could delve even further into the fray and check whether the actual type can be deduced...
... but do you realize that, as it is, the simple fact of allowing you to elide template in some circumstances (non-dependent situations) already requires one of the worst compiler hacks ever ? The traditional pipeline: tokenization -> parsing -> semantic analysis has to be completely twisted in C++ to allow feedback of semantic analysis during the parsing phase to automatically disambiguate that foo<4>() is a template call.
Personally, my recommendation would have been to mandate template systematically. It would have saved a lot of troubles.

SFINAE: Compiler doesn't pick the specialized template class

I have an SFINAE problem:
In the following code, I want the C++ compiler to pick the specialized functor and print "special", but it's printing "general" instead.
#include <iostream>
#include <vector>
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename T::Vec> {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
struct Foo {
typedef std::vector<int> Vec;
};
int main() {
Functor<Foo> ac;
ac();
}
How can I fix it so that the specialized struct is used automatically? Note I don't want to directly specialize the Functor struct on Foo, but I want to specialize it on all types that have a Vec type.
P.S.: I am using g++ 4.4.4
Sorry for misleading you in the last answer, I thought for a moment that it would be simpler. So I will try to provide a complete solution here. The general approach to solve this type of problems is to write a traits helper template and use it together with enable_if (either C++11, boost or manual implementation) to decide a class specialization:
Trait
A simple approach, not necessarily the best, but simple to write would be:
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test( typename U::Vec* p );
template <typename U>
static no test( ... );
static const bool value = sizeof( test<T>(0) ) == sizeof(yes);
};
The approach is simple, provide two template functions, that return types of different sizes. One of which takes the nested Vec type and the other takes ellipsis. For all those types that have a nested Vec the first overload is a better match (ellipsis is the worst match for any type). For those types that don't have a nested Vec SFINAE will discard that overload and the only option left will be the ellipsis. So now we have a trait to ask whether any type has a nested Vec type.
Enable if
You can use this from any library, or you can roll your own, it is quite simple:
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
When the first argument is false, the base template is the only option, and that does not have a nested type, if the condition is true, then enable_if has a nested type that we can use with SFINAE.
Implementation
Now we need to provide the template and the specialization that will use SFINAE for only those types with a nested Vec:
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
Whenever we instantiate Functor with a type, the compiler will try to use the specialization, which will in turn instantiate has_nested_Vec and obtain a truth value, passed to enable_if. For those types for which the value is false, enable_if does not have a nested type type, so the specialization will be discarded in SFINAE and the base template will be used.
Your particular case
In your particular case, where it seems that you don't really need to specialize the whole type but just the operator, you can mix the three elements into a single one: a Functor that dispatches to one of two internal templated functions based on the presence of Vec, removing the need for enable_if and the traits class:
template <typename T>
class Functor {
template <typename U>
void op_impl( typename U::Vec* p ) const {
std::cout << "specialized";
}
template <typename U>
void op_impl( ... ) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};
Even though this is an old question, I think it's still worth providing a couple more alternatives for quickly fixing the original code.
Basically, the problem is not with the use of SFINAE (that part is fine, actually), but with the matching of the default parameter in the primary template (void) to the argument supplied in the partial specialization(typename T::Vec). Because of the default parameter in the primary template, Functor<Foo> actually means Functor<Foo, void>. When the compiler tries to instantiate that using the specialization, it tries to match the two arguments with the ones in the specialization and fails, as void cannot be substituted for std::vector<int>. It then falls back to instantiating using the primary template.
So, the quickest fix, which assumes all your Vecs are std::vector<int>s, is to replace the line
template<class T, class V = void>
with this
template<class T, class E = std::vector<int>>
The specialization will now be used, because the arguments will match. Simple, but too limiting. Clearly, we need to better control the type of the argument in the specialization, in order to make it match something that we can specify as the default parameter in the primary template. One quick solution that doesn't require defining new traits is this:
#include <iostream>
#include <vector>
#include <type_traits>
template<class T, class E = std::true_type>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename std::is_reference<typename T::Vec&>::type> {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
struct Foo {
typedef std::vector<int> Vec;
};
int main() {
Functor<Foo> ac;
ac();
}
This will work for any Vec type that could make sense here, including fundamental types and arrays, for example, and references or pointers to them.
Another alternative for detecting the existence of a member type is to use void_t. As valid partial specialisations are preferable to the general implementation as long as they match the default parameter(s), we want a type that evaluates to void when valid, and is only valid when the specified member exists; this type is commonly (and, as of C++17, canonically) known as void_t.
template<class...>
using void_t = void;
If your compiler doesn't properly support it (in early C++14 compilers, unused parameters in alias templates weren't guaranteed to ensure SFINAE, breaking the above void_t), a workaround is available.
template<typename... Ts> struct make_void { typedef void type; };
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
As of C++17, void_t is available in the utilities library, in type_traits.
#include <iostream>
#include <vector>
#include <type_traits> // For void_t.
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
// Use void_t here.
template<class T>
struct Functor<T, std::void_t<typename T::Vec>> {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
struct Foo {
typedef std::vector<int> Vec;
};
int main() {
Functor<Foo> ac;
ac();
}
With this, the output is special, as intended.
In this case, since we're checking for the existence of a member type, the process is very simple; it can be done without expression SFINAE or the type_traits library, allowing us to rewrite the check to use C++03 facilities if necessary.
// void_t:
// Place above Functor's definition.
template<typename T> struct void_t { typedef void type; };
// ...
template<class T>
struct Functor<T, typename void_t<typename T::Vec>::type> {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
To my knowledge, this should work on most, if not all, SFINAE-capable C++03-, C++11-, C++14-, or C++1z-compliant compilers. This can be useful when dealing with compilers that lag behind the standard a bit, or when compiling for platforms that don't have C++11-compatible compilers yet.
For more information on void_t, see cppreference.

Reflection in known set of classes

I am trying to iterate through an object hierarchy and the object hierarchy is composed of a known set of classes combined using composition. I would like to build an object model to show the hierarchy / composition graphically. The composition is done based on few rules but it is fluid and flexible.
Quite a few classes (25+) are available and the number of building blocks is increasing. If I search each type in every other type then we have a significantly large number of combinations possible.
I could build a large table where I search for each of the other objects for a given type and recursively build the object model but may be there is a better way and so here I am asking the experts.
Is it possible to know if a function / member variable is present on a particular type at runtime.
My sample code is shown below :
#include <iostream>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <typename ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
};
int main(int argc, char *argv[])
{
// all this works fine
std::cout << TypeHasToString<Generic>::value << std::endl;
std::cout << TypeHasToString<SimpleType>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal1>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal2>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal3>>::value << std::endl;
// Unable to deduce for type that are not known at compile time
// Is it possible to remove this limitation ?
for(int val = eVal1; val <= eVal3; val++)
{
std::cout << TypeHasToString< Hello< (ETypeVal)val > >::value << std::endl;
}
return 0;
}
I've used boost::mpl to do the iteration and printing of the values. Most of this should be possible without any of those, but I heavily recommend using it. Also I've fixed some things in your code. You might also want to use BOOST_HAS_XXX instead of your homebrew solution (your SFINAE style is rather awkward).
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/for_each.hpp>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{ eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
public:
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
};
template<typename val>
struct make_hello { typedef Hello< ETypeVal(val::value)> type; };
struct print_seq {
template<typename T>
void operator()(const T&) const {
std::cout << T::value << std::endl;
}
};
int main()
{
using namespace boost::mpl;
// maybe have a last enum here
typedef range_c<int, eVal1, eVal3 + 1>::type range;
// range has no clear so we need the inserter
typedef transform<range, make_hello<_1>, back_inserter< vector0<> > >::type hellos;
typedef transform< hellos, TypeHasToString<_1> >::type booleans;
// namespace for clarity
boost::mpl::for_each<booleans>( print_seq() );
return 0;
}
We don't have run-time reflection in C++. But we have different stuff, that most C++ programmers like better than reflection ;-).
If I understand your question, you need to build some sort of object browser, and you know all your object types. By "you know all your object types" I mean "you won't get an object as something at the other end of a pointer from a dll you didn't code".
So, maybe you can use boost::fusion? Said library is designed for iterating through aggregates, and while doing so, retrieving both data and type of each aggregate member. It is like iterators over struct members, if I have to put it in a flowery way. You can of course use it with your custom types.
You can't know at runtime if you don't at compile time. You have the code to know at compile time for one function. You could just make a macro out of it to have it for any function you want to check. (Macro disclaimer: in this case macros are good, that's how BOOST_MPL_HAS_XXX_TEMPLATE_DEF works).
Alternatively, there's boost::fusion as mentionned by dsign. But I prefer another one: boost::reflect (not actully in boost more info here). The macro syntax is easier (you don't need to mention the type in the macro) and the code is very lightweight. Then there's the feature complete boost::mirror (download here), not yet in boost, that is much more complete and even has a code generator to create the macro calls for you and a java style runtime reflection.
I think that you need the runtime polymorphism in this case. Use interfaces instead of templates for such kind of problems. Interfaces will give the knowledge about of the methods in your object but will say nothing about the member variables. So there is no reflection available in standard c++ (the only thing that c++ provides is the type_info operator which might help you in some cases), you could try to find some extensions for your compiler which will give you the reflection opportunities.