Non-type variadic function templates in C++11
You are simply confusing type names and non-type names. What you want simply doesn’t work.
You can probably use variadic non-type templates in functions, but not as (non-template) arguments:
template <int N, int... Rest>
int max()
{
int tmp = max<Rest...>();
return N < tmp ? tmp : N;
}
std::cout << max<3, 1, 4, 2, 5, 0>() << std::endl;
… although I haven’t tested this and I’m not sure how this should work given that you need to have a partial specialisation as the base case. You could solve this by dispatching to a partially specialised struct:
template <int N, int... Rest>
struct max_t {
static int const value = max_t<Rest...>::value > N ? max_t<Rest...>::value : N;
};
template <int N>
struct max_t<N> {
static int const value = N;
};
template <int... NS>
int max()
{
return max_t<NS...>::value;
}
This will work.
How to resolve this issue with variadic non-type template parameter in C++11?
Here's a solution using std::integer_sequence
. It's a C++14 feature, but ports to C++11 do exist (haven't used this, can't vouch for its quality).
template<Enum... es>
class B
{
template <int... Is>
static std::shared_ptr<A> getAHelper(std::integer_sequence<Is...>) {
return std::make_shared<A>(translate(es, Is)...);
}
public:
static std::shared_ptr<A> getA()
{
return getAHelper(std::make_integer_sequence<sizeof...(es)>{});
}
};
C++ variadic template with non-type parameters of different types
You can do it in the following way:
template <class... Types>
struct Wrapper
{
template <Types... args>
class Test {
// ...
};
};
Note that simple notation template <class... Types, Types... args> class Test;
is not permitted by standard (see paragraph [temp.param] 14.1/15).
Example of using (note that float
, double
and long double
constants can not be non-type template parameters):
Wrapper<int, char, unsigned>::Test<1, '2', 3U> t;
More specific case with pointers to members can be implemented similarly:
struct Base
{
int a;
float b;
void c() {}
};
template <class... Types>
struct Wrapper
{
template <Types Base::*... args>
class Test {
//
};
};
Example of using:
Wrapper<int, float, void ()>::Test<&Base::a, &Base::b, &Base::c> t2;
This notation can be shortened using variadic macro and decltype
keyword.
Template template parameter with mixed type and non-type variadic parameters
It is possible with some modifications:
//type container template
template<typename...>
struct types{};
//declaration
template<typename ,auto V, typename, template<typename ,decltype(V), typename...>class>
class enum_to_type;
//generic definition
template<typename First, typename ... Befors, First V, typename ... Afters, template<typename ,First, typename...>class U>
class enum_to_type<types<First, Befors...>, V, types<Afters...>, U>{
public:
static auto go(){
return U<types<Befors...>, V + 1, Afters...>{};
}
};
//specialization
template<auto V, typename ... Afters, template<typename ,decltype(V), typename...>class U>
class enum_to_type<types<>, V,types<Afters...>, U>{
public:
static auto go(){
return U<types<>, V + 1, Afters...>{};
//or
//return U<types<>, V, Afters...>{};
}
};
//Declarations and specializations for the target class templates
template<typename, int>
struct A{};
template<typename, int, typename>
struct B;
template<typename T, int V>
struct B<types<>, V, T > {};
using next_A = decltype(enum_to_type<types<int>, 0, types<>, A>::go());
template<typename T>
using next_B = decltype(enum_to_type<types<int>, 0, types<T>, B>());
template<typename, auto, typename...>
struct general_case;
template<typename ... befors, int V, typename ... afters>
struct general_case<types<befors...>, V, afters ...> {};
Usage:
decltype(enum_to_type<types<>, 0, types<>, A>::go()) object_A;
decltype(enum_to_type<types<>, 0, types<int>, B>::go()) object_B;
decltype(enum_to_type<types<int, float>, 3, types<int>, general_case>::go()) object_general;
It is just that compiler does not have a way to find out how many types are in before and after. That is why in general it can take only one arguments pack in template declaration. But it can handle multiple arguments packs in specialization!
Good luck!
Non-type variadic template parameter
What's wrong is [temp.arg.nontype] §2.3. String literals cannot (currently) be used as template arguments. What you could do, for example, is declare named array objects and use those as arguments:
template<const wchar_t* ...properties>
class my_iterator {};
int main()
{
static constexpr const wchar_t a[] = L"hello";
static constexpr const wchar_t b[] = L"world";
my_iterator<a, b> inst;
}
working example here
C++ variadic templates with type and non-type argument mixing for recursive inheritance
It's not possible. You'll have to settle for one of the following:
Foo<Bar<int, 5>, Bar<double, 7>> foo_1;
Foo<int, Bar<5>, double, Bar<7>> foo_1;
// ...?
If the values are always integral, you could also try this:
Foo<int[5], double[7]> foo_1;
And then extract elemenet types & extents from each argument.
c++ non-type parameter pack expansion
I see two options here. You can pass a std::initializer_list
, which causes the function signature to change to
#include <initializer_list>
template <typename T>
static bool value_in(T&& val, std::initializer_list<T> vals)
{
/* Implementation as before */
}
and the calling snippet to
return value_in(Enumeration::two,
{ Enumeration::one, Enumeration::two }) ? 0 : 1;
Note the additional braces here, they are required to construct the initializer list to be passed. A little detail of this approach is the function signature, which immediately reveals that there is only one type to deduce.
If it feels wrong to type the braces, stick with your original attempt and tweak your function such that
template <typename S, typename... T>
static bool value_in(S&& val, T&&... vals) {
const std::unordered_set<S> allowed {std::forward<T>(vals)...};
/* As before... */
}
This allows for calling the function as in your original snippet. In contrast to the above solution, this signature obviously has two template parameters, which might require a second look to see that it will fail if S
differs from T
.
Related Topics
Const Member and Assignment Operator. How to Avoid the Undefined Behavior
Best C++ Development Environment in Linux
How to Invoke Pointer to Member Function When It's a Class Data Member
Can Someone Explain About Linux Library Naming
Calculate Md5 of a String in C++
What Does a Comma Separated List of Values, Enclosed in Parenthesis Mean in C? a = (1, 2, 3);
How to Restart Linux from Inside a C++ Program
Dll Main on Windows VS. _Attribute_((Constructor)) Entry Points on Linux
Set System Date and Time Using C++ in Linux
Access Violation Writing Location 0Xcccccccc
Improving Mmap Memcpy File Read Performance
Does the Alignas Specifier Work with 'New'
How to Calculate a Sha-512 Hash in C++ on Linux
C++ What Happens When in One Thread Write and in Second Read the Same Object? (Is It Safe)
C++ Access to SQL Server from Linux