template parameter pack in using - c++

How i can use "using" keyword in multiple inheritance when parameter pack is template parameter of base class?
Code below compiles just fine
struct A
{
void foo(int) {}
};
struct B
{
void foo(int) {}
};
template<typename ...Types>
struct C : public Types...
{
using Types::foo...;
};
int main()
{
C<A,B> c;
}
But if i use template instead of A and B - I've got compile error
template<typename T>
struct TA {};
template<>
struct TA<int>
{
void foo(int) {}
};
template<>
struct TA<double>
{
void foo(int) {}
};
template<typename ...Types>
struct TC : public TA<Types>...
{
using TA<Types>::foo...; // ERROR C3520
};
Error:
error C3520: 'Types': parameter pack must be expanded in this context
How to rewrite second piece of code to get it work?
PS
I tried this code with gcc and it's compiles without errors. But now I am using msvc...

Since it's a known MSVC bug, if you still want to make this work with MSVC you'll have to do it the (not very) hard way:
template <typename ...Types>
struct TC;
template <typename T>
struct TC<T> : TA<T>
{
using TA<T>::foo;
};
template <typename T, typename ...Types>
struct TC<T, Types...> : public TC<T>, public TC<Types...>
{
using TC<T>::foo;
using TC<Types...>::foo;
};

Related

Is there a way to disable member function in a template class in c++ for visual studio 2010 ( no default function template params )

For example
#include "boost/type_traits.hpp"
template <bool enable>
struct Foo {
template <bool e = enable>
typename boost::enable_if_c<e,void>::type DoStuff(){}
};
int main(){
// Compiles
Foo<true>().DoStuff();
// Fails
Foo<false>().DoStuff();
}
will work in modern compilers but not with visual studio 2010 which does not allow default template params for functions / methods. Is there another way to formulate the same task that will work with VS2010?
You could specialize the entire class like
template <bool enable>
struct Foo {};
template <>
struct Foo<true> {
void DoStuff(){}
};
template <>
struct Foo<false> {
};
And then
int main(){
// Compiles
Foo<true>().DoStuff();
// Fails
Foo<false>().DoStuff();
}
You could discard DoStuff via SFINAE:
template<bool enable>
struct Foo {
private:
static void SFINAE_Helper(std::true_type);
typedef std::integral_constant<bool, enable> tag;
public:
decltype(SFINAE_Helper(tag())) DoStuff() { }
};
Besides the fact that this code is quite unreadable it has the advantage, that you do not need to make extra specializations but can have all your code in one class template.
EDIT
An alternative could look like that:
template<bool enable>
struct Foo {
private:
typedef std::enable_if<enable> enable_tag;
public:
typename enable_tag::type DoStuff() {}
};

Using declaration contains unexpanded parameter pack

How do I get this code to compile?
struct type1 {};
struct type2 {};
struct handler1
{
void handle(type1){}
};
struct handler2
{
void handle(type2){}
};
template <typename... Handlers>
struct TheHandler : Handlers...
{
using Handlers::handle...; // DOESN'T COMPILE
};
TheHandler<handler1, handler2> handler;
handler.handle(type1());
using with parameter packs was added in C++17, so your code would just work in C++17.
As a workaround for C++14, you can use recursion. The proposal for using... shows how to do this:
template <typename Handler0, typename... Handlers>
struct TheHandler : Handler0, TheHandler<Handlers...>
{
using Handler0::handle;
using TheHandler<Handlers...>::handle;
};
template <typename Handler>
struct TheHandler<Handler> : Handler
{
using Handler::handle;
};
On Godbolt
It is possible to achieve logarithmic recursion depth, if you wish to do so.

C++: Partially specializing template's type parameter as another template class's member-type

I have a template struct SFoo that contains a member struct SZug:
template <typename tTYPE>
struct SFoo
{
struct SZug {};
};
I have another struct SBar that takes a type parameter:
template <typename tTYPE>
struct SBar
{ /* stuff */ };
I would like to specialize SBar using SZug for the type parameter, like so:
template <typename tTYPE>
struct SBar<typename SFoo<tTYPE>::SZug>
{ /* different stuff */ };
This doesn't compile - LLVM outputs:
non-deducible template parameter 'tTYPE'
While a compiler could easily deduce this if it wished, I'm guessing it's just that the C++ spec would need to specifically cover this case.
Is there any way to achieve this?
(note: I'm currently working around it by moving SZug outside of SFoo and using a using declaration, but it's ugly.)
I am not sure I fully understood what you want to do, but you could try the following (it only requires adding a specific attributes to SZug:
template <typename tTYPE>
struct SFoo {
struct SZug {
// Add this to be able to obtain SFoo<T> from SFoo<T>::SZug
using type = tTYPE;
};
};
Then a small template to check if a type is a SFoo<T>::SZug:
template <typename tTYPE, typename Enabler = void>
struct is_SZug: public std::false_type { };
template <typename tTYPE>
struct is_SZug<tTYPE, typename std::enable_if<
std::is_same<tTYPE, typename SFoo<typename tTYPE::type>::SZug>{}
>::type>: public std::true_type { };
And a slight modification to the SBar template to enable the "specialization" if the type is a SZug:
template <typename tTYPE, typename Enabler = void>
struct SBar
{ static void g(); };
template <typename tTYPE>
struct SBar<tTYPE, typename std::enable_if<is_SZug<tTYPE>{}>::type>
{ static void f(); };
A little check:
void f () {
SBar<int>::g();
SBar<SFoo<int>::SZug>::f();
}
Note: You could also directly set SFoo<T> as the type attribute in SFoo<T>::SZug, you would simply need to change the second argument of std::is_same a little.
You can get the effect for which you're looking through the following (which prints out 0 1, BTW):
#include <type_traits>
#include <iostream>
namespace detail
{
struct SZugBase{};
}
template <typename tTYPE>
struct SFoo
{
struct SZug : public detail::SZugBase {};
};
template<typename tType, bool IsFoo>
struct SBarBase
{
int value = 0;
};
template<typename tType>
struct SBarBase<tType, true>
{
int value = 1;
};
template <typename tTYPE>
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value>
{ /* stuff */ };
int main()
{
SBar<int> b0;
SBar<SFoo<int>::SZug> b1;
std::cout << b0.value << " " << b1.value << std::endl;
}
Explanation
First, we give SZug a regular-class base:
namespace detail
{
struct SZugBase{};
}
template <typename tTYPE>
struct SFoo
{
struct SZug : public detail::SZugBase {};
};
Note the following:
SZugBase is not parameterized by anything, so it is easy to refer to it independently of the parameter of SFoo
SZugBase is in a detail namespace, so, by common C++ conventions, you're telling clients of your code to ignore it.
Now we give SBar two base classes, specialized on whether something is convertible to the non-template base of SZug:
template<typename tType, bool IsFoo>
struct SBarBase
{
int value = 0;
};
template<typename tType>
struct SBarBase<tType, true>
{
int value = 1;
};
Finally, we just need to make SBar a subclass of these bases (depending on the specialization):
template <typename tTYPE>
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value>
{ /* stuff */ };
Note that you don't specialize SBar here, you rather specialize the base classes. This effectively gives the same effect, though.

Using member declaration with enable_if?

I need conditional using member declaration.
template <bool> struct B;
template <> struct B<true> { void foo(); };
template <> struct B<false> { };
template <typename T>
struct A : public B<is_default_constructible<T>::value> {
using B<is_default_constructible<T>::value>::foo();
void foo(int) {}
};
This obviously doesn't work, because B<bool>::foo is not defined
in half the cases. How can I achieve that? To have B<>::foo()
visible in A<T> scope beside foo(int)?
Thanks for help
This is my solution. I'm sure it's won't be the best but it gets the job done.
struct A {
void foo(int) {}
};
struct A should contain methods you want defined in both cases.
template <bool> struct B;
template <> struct B<false> : A {};
template <> struct B<true> : A {
using A::foo;
void foo() {}
};
In case of B<false>, only void foo(int) is defined. In case of B<true>, both void foo(int) and void foo() are defined.
template <typename T>
struct C : public B<is_default_constructible<T>::value> {};
Now I don't have to worry about B<is_default_constructible<T>::value>::foo() not being defined in certain cases.
class D { D() = delete; };
int main()
{
C<int> c1;
c1.foo(1234);
c1.foo();
// both methods are defined for C<int>
C<D> c2;
c2.foo(1234);
// c2.foo(); // undefined method
return 0;
}
Use specialization.
enable_if can't be used for that. You need to specialize struct A too.
#include <type_traits>
template <bool> struct B;
template <> struct B<true> { void foo(); };
template <> struct B<false> { };
template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
struct A : public B<default_constructible> {
using B<default_constructible>::foo;
void foo(int) {}
};
template<typename T>
struct A<T, false> : public B<false> {
void foo(int) {}
};
Avoiding duplicate code for foo(int)
If foo(int) will have the same functionality in both cases, you may want to derive it from another base struct:
#include <type_traits>
template <bool> struct B;
template <> struct B<true> { void foo(); };
template <> struct B<false> { };
template<typename T>
struct C {
void foo(int) {}
};
template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
struct A : public B<default_constructible>, public C<T> {
using B<default_constructible>::foo;
using C<T>::foo;
};
template<typename T>
struct A<T, false> : public B<false>, public C<T> {
using C<T>::foo;
};
Removing that ugly bool
Finally, to remove that bool from struct A's template parameters, you may want to forward the responsibility of selecting the overloads of foo to a base class. This also has the advantage of not duplicating code for other struct A's members you may want to add.
#include <type_traits>
template <bool> struct B;
template <> struct B<true> { void foo(); };
template <> struct B<false> { };
template<typename T>
struct C {
void foo(int) {}
};
template <typename T, bool default_constructible = std::is_default_constructible<T>::value>
struct base_A : public B<default_constructible>, public C<T> {
using B<default_constructible>::foo;
using C<T>::foo;
};
template<typename T>
struct base_A<T, false> : public B<false>, public C<T> {
using C<T>::foo;
};
template <typename T>
struct A : public base_A<T> {
// Other members.
};

Problems with enable_if SFINAE

I have been having some inexplicable SFINAE problems in a program I'm writing, so I boiled it down to a freestanding example program:
#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
template<typename U>
To(const From<U>& other) {
static_assert(std::is_convertible<U*, T*>::value, "error");
}
};
int main() {
From<Derived> a;
To<Base> b = a;
}
This program compiles without error or warning. However, this:
#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
template<typename U>
To(const From<typename std::enable_if<true, U>::type>& other) {
// this ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
static_assert(std::is_convertible<U*, T*>::value, "error");
}
};
int main() {
From<Derived> a;
To<Base> b = a;
}
Gives the following error:
test.cpp: In function int main():
test.cpp:22:18: error: conversion from From<Base> to non-scalar type To<Derived> requested
Which is because the substitution fails I presume, and the constructor isn't seen.
Am I doing SFINAE wrong, or is this a compiler bug? I am using rubenvb's GCC 4.7.1 on Windows (with std=c++11 if it makes a difference).
I'd use a default template argument, that way the argument can be deduced:
#include <type_traits>
struct Base { };
struct Derived : public Base { };
template<typename T>
struct From { };
template<typename T>
struct To {
template<typename U, class = typename std::enable_if<true, U>::type>
To(const From<U>& other) {
// this ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
static_assert(std::is_convertible<U*, T*>::value, "error");
}
};
int main() {
From<Base> a;
To<Derived> b = a;
}
Note that that causes the static_assert to fail since you are using std::is_convertible the other way around. It should be:
static_assert(std::is_convertible<T*, U*>::value, "error");
In your example, the template type U can't be deduced. In my code, it can be deduced, since it is being used as a template argument for the other argument in the constructor. In your code, the compiler sees a std::enable_if<true, U>::type and can't deduce what that U type is. The fact that the result of that enable_if is being used as a template argument for From doesn't help at all, since U needs to be deduced before that.