Error C2752 on template template parameter with variadic non-type template parameter specializations - visual-studio-2017

I need some advice.
On VS2017 (MSVC 14.16.27023) and VS2019 (MSVC 14.27.29110) with c++17 the following code fails:
#include <cstdint>
#include <iostream>
template<int A>
struct Bar {};
template<typename T>
struct Foo
{
static void f() { std::cout << "FOO" << std::endl; }
};
template<template<int...> class C, int... Args>
struct Foo<C<Args...>>
{
static void f() { std::cout << "FOO int spec" << std::endl; }
};
template<template<long...> class C, long... Args>
struct Foo<C<Args...>>
{
static void f() { std::cout << "FOO long spec" << std::endl; }
};
int main(void)
{
Foo<Bar<1>> foo;
foo.f();
}
with the following error:
'Foo<Bar<1>>': more than one partial specialization matches the template argument list
note: could be 'Foo<C<Args...>>'
note: or 'Foo<C<Args...>>'
(the "note"s are pointing to the line Foo<Bar<1> foo;)
As I see it it should be able to determine which specialization to use. Also, on VS2015 (MSVC 14.0.23107.0) it does compiles and works correctly.
The interesting part is that if Bar has 2 template parameters it works by matching to the primary template (the first one).
template<int A, int B>
struct Bar {};
However if the second template parameter has default value it doesn't compile again.
template<int A, int B = 1>
struct Bar {};
Is there a way to make this work on VS2017/2019, or should I file a bug report on VS forum?

Related

SFINAE in C++98

I am trying to understand how does SFINAE work in C++98.
My aim is to write a simple template function that would only be called when
an integer is passed. But the plan is to do it without specializing a function for typename T = int, but definining a template function with a dummy parameter that checks wether the pased element is an integer. Heres my toy code :
// header.h
#include <iostream>
#include <cstddef>
struct false_type {
static const bool value = false;
};
struct true_type {
static const bool value = true;
};
template < bool, typename T >
struct enable_if
{};
template <typename T>
struct enable_if<true, T>
{ typedef T type; };
template <typename T>
struct is_integral : false_type {};
template <>
struct is_integral<int> : true_type {};
/* ... more is_integral specializations ... */
template < typename T >
void print(T& value, typename enable_if<!is_integral<T>::value,T>::type* = 0)
{
std::cout << "FIRST " << value << std::endl;
}
template < typename T >
void print(T& value)
{
std::cout << "SECOND " << value << std::endl;
std::cout << std::boolalpha;
std::cout << is_integral<T>::value << std::endl;
}
// main.cpp
#include "header.hpp"
int main() {
int a = 123;
print<int>(a);
}
It is compiled as follows : g++ -Wall -Wextra -Werror -std=c++98 -pedantic -g3 -Wno-c++0x-compat main.cpp .
I took the enable_if syntax from this question's first answer, which needed for an implementation of enable_if and is_integral to be carried out in C++98 (<type_traits> is not a C++98 header).
My problem is that this program outputs:
SECOND 123
true
My question is, why does this happen? I expected the first implementation of print to be called. Is my approach impossible (i.e. this can only be done by specializing a generic print function to int), or am I doing something wrong ?
My aim is to write a simple template function that would only be called when an integer is passed.
There is no need to provide 2 overloads. You can just remove the ! and have the first primary template as shown below:
template < typename T >
void print(T& value, typename enable_if<is_integral<T>::value,T>::type* = 0)
{
std::cout << "FIRST " << value << std::endl;
}
int main() {
int a = 123;
print<int>(a); //works
//print<double>(4.4); //doesn't work
//print<std::string>(std::string("f")); //doesn't work
//print(3.3); //doesn't work
double d = 3.3;
//print(d); //doesn't work
}

Could you please explain below code ? It compiles fine. Its related to check whether given class is base of another class [duplicate]

I want to get into more template meta-programming. I know that SFINAE stands for "substitution failure is not an error." But can someone show me a good use for SFINAE?
I like using SFINAE to check boolean conditions.
template<int I> void div(char(*)[I % 2 == 0] = 0) {
/* this is taken when I is even */
}
template<int I> void div(char(*)[I % 2 == 1] = 0) {
/* this is taken when I is odd */
}
It can be quite useful. For example, i used it to check whether an initializer list collected using operator comma is no longer than a fixed size
template<int N>
struct Vector {
template<int M>
Vector(MyInitList<M> const& i, char(*)[M <= N] = 0) { /* ... */ }
}
The list is only accepted when M is smaller than N, which means that the initializer list has not too many elements.
The syntax char(*)[C] means: Pointer to an array with element type char and size C. If C is false (0 here), then we get the invalid type char(*)[0], pointer to a zero sized array: SFINAE makes it so that the template will be ignored then.
Expressed with boost::enable_if, that looks like this
template<int N>
struct Vector {
template<int M>
Vector(MyInitList<M> const& i,
typename enable_if_c<(M <= N)>::type* = 0) { /* ... */ }
}
In practice, i often find the ability to check conditions a useful ability.
Heres one example (from here):
template<typename T>
class IsClassT {
private:
typedef char One;
typedef struct { char a[2]; } Two;
template<typename C> static One test(int C::*);
// Will be chosen if T is anything except a class.
template<typename C> static Two test(...);
public:
enum { Yes = sizeof(IsClassT<T>::test<T>(0)) == 1 };
enum { No = !Yes };
};
When IsClassT<int>::Yes is evaluated, 0 cannot be converted to int int::* because int is not a class, so it can't have a member pointer. If SFINAE didn't exist, then you would get a compiler error, something like '0 cannot be converted to member pointer for non-class type int'. Instead, it just uses the ... form which returns Two, and thus evaluates to false, int is not a class type.
In C++11 SFINAE tests have become much prettier. Here are a few examples of common uses:
Pick a function overload depending on traits
template<typename T>
std::enable_if_t<std::is_integral<T>::value> f(T t){
//integral version
}
template<typename T>
std::enable_if_t<std::is_floating_point<T>::value> f(T t){
//floating point version
}
Using a so called type sink idiom you can do pretty arbitrary tests on a type like checking if it has a member and if that member is of a certain type
//this goes in some header so you can use it everywhere
template<typename T>
struct TypeSink{
using Type = void;
};
template<typename T>
using TypeSinkT = typename TypeSink<T>::Type;
//use case
template<typename T, typename=void>
struct HasBarOfTypeInt : std::false_type{};
template<typename T>
struct HasBarOfTypeInt<T, TypeSinkT<decltype(std::declval<T&>().*(&T::bar))>> :
std::is_same<typename std::decay<decltype(std::declval<T&>().*(&T::bar))>::type,int>{};
struct S{
int bar;
};
struct K{
};
template<typename T, typename = TypeSinkT<decltype(&T::bar)>>
void print(T){
std::cout << "has bar" << std::endl;
}
void print(...){
std::cout << "no bar" << std::endl;
}
int main(){
print(S{});
print(K{});
std::cout << "bar is int: " << HasBarOfTypeInt<S>::value << std::endl;
}
Here is a live example: http://ideone.com/dHhyHE
I also recently wrote a whole section on SFINAE and tag dispatch in my blog (shameless plug but relevant) http://metaporky.blogspot.de/2014/08/part-7-static-dispatch-function.html
Note as of C++14 there is a std::void_t which is essentially the same as my TypeSink here.
Boost's enable_if library offers a nice clean interface for using SFINAE. One of my favorite usage examples is in the Boost.Iterator library. SFINAE is used to enable iterator type conversions.
Here's another (late) SFINAE example, based on Greg Rogers's answer:
template<typename T>
class IsClassT {
template<typename C> static bool test(int C::*) {return true;}
template<typename C> static bool test(...) {return false;}
public:
static bool value;
};
template<typename T>
bool IsClassT<T>::value=IsClassT<T>::test<T>(0);
In this way, you can check the value's value to see whether T is a class or not:
int main(void) {
std::cout << IsClassT<std::string>::value << std::endl; // true
std::cout << IsClassT<int>::value << std::endl; // false
return 0;
}
Examples provided by other answers seems to me more complicated than needed.
Here is the slightly easier to understand example from cppreference :
#include <iostream>
// this overload is always in the set of overloads
// ellipsis parameter has the lowest ranking for overload resolution
void test(...)
{
std::cout << "Catch-all overload called\n";
}
// this overload is added to the set of overloads if
// C is a reference-to-class type and F is a pointer to member function of C
template <class C, class F>
auto test(C c, F f) -> decltype((void)(c.*f)(), void())
{
std::cout << "Reference overload called\n";
}
// this overload is added to the set of overloads if
// C is a pointer-to-class type and F is a pointer to member function of C
template <class C, class F>
auto test(C c, F f) -> decltype((void)((c->*f)()), void())
{
std::cout << "Pointer overload called\n";
}
struct X { void f() {} };
int main(){
X x;
test( x, &X::f);
test(&x, &X::f);
test(42, 1337);
}
Output:
Reference overload called
Pointer overload called
Catch-all overload called
As you can see, in the third call of test, substitution fails without errors.
C++17 will probably provide a generic means to query for features. See N4502 for details, but as a self-contained example consider the following.
This part is the constant part, put it in a header.
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf.
template <typename...>
using void_t = void;
// Primary template handles all types not supporting the operation.
template <typename, template <typename> class, typename = void_t<>>
struct detect : std::false_type {};
// Specialization recognizes/validates only types supporting the archetype.
template <typename T, template <typename> class Op>
struct detect<T, Op, void_t<Op<T>>> : std::true_type {};
The following example, taken from N4502, shows the usage:
// Archetypal expression for assignment operation.
template <typename T>
using assign_t = decltype(std::declval<T&>() = std::declval<T const &>())
// Trait corresponding to that archetype.
template <typename T>
using is_assignable = detect<T, assign_t>;
Compared to the other implementations, this one is fairly simple: a reduced set of tools (void_t and detect) suffices. Besides, it was reported (see N4502) that it is measurably more efficient (compile-time and compiler memory consumption) than previous approaches.
Here is a live example, which includes portability tweaks for GCC pre 5.1.
Here is one good article of SFINAE: An introduction to C++'s SFINAE concept: compile-time introspection of a class member.
Summary it as following:
/*
The compiler will try this overload since it's less generic than the variadic.
T will be replace by int which gives us void f(const int& t, int::iterator* b = nullptr);
int doesn't have an iterator sub-type, but the compiler doesn't throw a bunch of errors.
It simply tries the next overload.
*/
template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { }
// The sink-hole.
void f(...) { }
f(1); // Calls void f(...) { }
template<bool B, class T = void> // Default template version.
struct enable_if {}; // This struct doesn't define "type" and the substitution will fail if you try to access it.
template<class T> // A specialisation used if the expression is true.
struct enable_if<true, T> { typedef T type; }; // This struct do have a "type" and won't fail on access.
template <class T> typename enable_if<hasSerialize<T>::value, std::string>::type serialize(const T& obj)
{
return obj.serialize();
}
template <class T> typename enable_if<!hasSerialize<T>::value, std::string>::type serialize(const T& obj)
{
return to_string(obj);
}
declval is an utility that gives you a "fake reference" to an object of a type that couldn't be easily construct. declval is really handy for our SFINAE constructions.
struct Default {
int foo() const {return 1;}
};
struct NonDefault {
NonDefault(const NonDefault&) {}
int foo() const {return 1;}
};
int main()
{
decltype(Default().foo()) n1 = 1; // int n1
// decltype(NonDefault().foo()) n2 = n1; // error: no default constructor
decltype(std::declval<NonDefault>().foo()) n2 = n1; // int n2
std::cout << "n2 = " << n2 << '\n';
}
The following code uses SFINAE to let compiler select an overload based on whether a type has certain method or not:
#include <iostream>
template<typename T>
void do_something(const T& value, decltype(value.get_int()) = 0) {
std::cout << "Int: " << value.get_int() << std::endl;
}
template<typename T>
void do_something(const T& value, decltype(value.get_float()) = 0) {
std::cout << "Float: " << value.get_float() << std::endl;
}
struct FloatItem {
float get_float() const {
return 1.0f;
}
};
struct IntItem {
int get_int() const {
return -1;
}
};
struct UniversalItem : public IntItem, public FloatItem {};
int main() {
do_something(FloatItem{});
do_something(IntItem{});
// the following fails because template substitution
// leads to ambiguity
// do_something(UniversalItem{});
return 0;
}
Output:
Float: 1
Int: -1
Here, I am using template function overloading (not directly SFINAE) to determine whether a pointer is a function or member class pointer: (Is possible to fix the iostream cout/cerr member function pointers being printed as 1 or true?)
https://godbolt.org/z/c2NmzR
#include<iostream>
template<typename Return, typename... Args>
constexpr bool is_function_pointer(Return(*pointer)(Args...)) {
return true;
}
template<typename Return, typename ClassType, typename... Args>
constexpr bool is_function_pointer(Return(ClassType::*pointer)(Args...)) {
return true;
}
template<typename... Args>
constexpr bool is_function_pointer(Args...) {
return false;
}
struct test_debugger { void var() {} };
void fun_void_void(){};
void fun_void_double(double d){};
double fun_double_double(double d){return d;}
int main(void) {
int* var;
std::cout << std::boolalpha;
std::cout << "0. " << is_function_pointer(var) << std::endl;
std::cout << "1. " << is_function_pointer(fun_void_void) << std::endl;
std::cout << "2. " << is_function_pointer(fun_void_double) << std::endl;
std::cout << "3. " << is_function_pointer(fun_double_double) << std::endl;
std::cout << "4. " << is_function_pointer(&test_debugger::var) << std::endl;
return 0;
}
Prints
0. false
1. true
2. true
3. true
4. true
As the code is, it could (depending on the compiler "good" will) generate a run time call to a function which will return true or false. If you would like to force the is_function_pointer(var) to evaluate at compile type (no function calls performed at run time), you can use the constexpr variable trick:
constexpr bool ispointer = is_function_pointer(var);
std::cout << "ispointer " << ispointer << std::endl;
By the C++ standard, all constexpr variables are guaranteed to be evaluated at compile time (Computing length of a C string at compile time. Is this really a constexpr?).

static_assert that a member variable is marked as 'static' in C++17?

I've been playing around with templates and would like to enforce that a template type given to a function has a particular static member. Unfortunately, there is no std::is_static type trait.
A rough example of how I would use it (or an alternative):
template<typename T>
void SomeFunc(T& obj)
{
static_assert(std::is_static_v<decltype(T::someVariable)>, "someVariable must be static");
}
Are there any ways to achieve this kind of behaviour? I could just write
template<typename T>
void SomeFunc(T& obj)
{
// must be static
T::someVariable;
}
But this wouldn't be anywhere near as nice or informative as a static_assert with a decent message. This is just a syntax error of sorts :(
Thanks!
If I understand correctly what you want, you're looking for std::is_member_pointer (or the opposite of the value of std::is_member_pointer).
An example (also C++11 and C++14 compliant)
#include <type_traits>
struct foo
{ int value; };
struct bar
{ static int value; };
int main()
{
static_assert(
true == std::is_member_pointer<decltype(&foo::value)>::value, "!");
static_assert(
false == std::is_member_pointer<decltype(&bar::value)>::value, "!!");
}
-- EDIT --
Not sure to understand the nakiya's objection but ... in the following example I've developed a type traits (hasSomeValueStatic) that set value to true if the template argument has a someValue static member and false otherwhise (if someValue isn't static of there isn't someValue.
#include <iostream>
#include <type_traits>
struct foo
{ int someValue; };
struct bar
{ static int someValue; };
template <typename, typename = int>
struct hasSomeValueStatic : std::false_type
{ };
template <typename T>
struct hasSomeValueStatic<T, decltype(T::someValue, 0)>
: std::integral_constant<bool,
! std::is_member_pointer<decltype(&T::someValue)>::value>
{ };
int main()
{
std::cout << hasSomeValueStatic<foo>::value << std::endl; // print 0
std::cout << hasSomeValueStatic<bar>::value << std::endl; // print 1
std::cout << hasSomeValueStatic<int>::value << std::endl; // print 0
}

Template class specialization for vector type - different valid syntax?

In the following snippit, is the template<> optional for the specialization? Is there any difference whether I include it or not? My first instinct was to include it as it more-or-less signifies that it is a specialization. It compiles both ways under both g++ 4.9.2 and Intel 16
#include <vector>
#include <iostream>
template<typename T>
struct PrintMe
{
static void Print(const T & t)
{
std::cout << "In general templated struct: " << t << "\n";
}
};
template<> // <--- optional?
template<typename T>
struct PrintMe<std::vector<T>>
{
static void Print(const std::vector<T> & t)
{
std::cout << "In general specialization for vector: " << t.size() << "\n";
for(const auto & it : t)
std::cout << " " << it << "\n";
}
};
int main(void)
{
PrintMe<int>::Print(5);
PrintMe<double>::Print(5);
PrintMe<std::vector<float>>::Print({10,20,30,40});
return 0;
}
Note: Out of curiosity, I tried adding multiple template<>. Ie,
template<>
template<>
template<>
template<typename T>
struct PrintMe<std::vector<T>>
This still compiles with Intel, but not with g++. Not sure what that means, but it's interesting.
Note 2: Wow, this is very similar to a question of mine from 5 years ago: Templated class specialization where template argument is a template . There it was mentioned as redundant syntax.
Given the definition of the class template,
template<> // <--- optional?
template<typename T>
struct PrintMe<std::vector<T>> { ... };
is not valid.
You need to remove that line and use:
template<typename T>
struct PrintMe<std::vector<T>> { ... };
there are ways to look at templates and template specialization that will paint a better picture and make the whole thing clearer.
For me in this case the easier way to look at this is not to think of
template<typename T>
struct PrintMe<std::vector<T>> { ... };
as a specialization of
template<typename T>
struct PrintMe { ... };
but as a different class template altogether, it just happen to be that the two have similarly named methods.

C++11 is there a way to test method access level statically?

C++11 adds lots of new class templates which allow to test type traits statically, i.e. detect problems at compile time. I'm writing a test for a class and I need to make sure a given method is public.
The "dynamic" solution is to create an object and call the method, then the compiler will complain if it doesn't work. But it's possible a different kind of error occurs, and it will make the resulting error message more confusing. If possible, it would be best to test method access level using static assertion.
Is it possible or I really have to create an object for that?
(also, what do I do if I need the method to be private/protected)
This compiles for me:
#include <type_traits>
namespace has_foo_imp
{
template <class T>
auto
test(T&& t) -> decltype(t.foo(), std::true_type());
auto
test(...) -> std::false_type;
} // has_foo_imp
template <class T>
struct has_foo
: public std::integral_constant<bool,
decltype(has_foo_imp::test(std::declval<T>()))::value>
{
};
class A
{
void foo();
public:
};
class B
{
public:
void foo();
};
int
main()
{
static_assert(!has_foo<A>::value, "");
static_assert( has_foo<B>::value, "");
}
As far as I can tell, the following is standards compliant:
#include <type_traits>
template<typename T,typename=void>
struct NullaryFooCanBeCalled:std::false_type {};
template<typename T>
struct NullaryFooCanBeCalled<
T,
typename std::enable_if<
std::is_same<
decltype(std::declval<T>().Foo()),
decltype(std::declval<T>().Foo())
>::value >::type
>:
std::true_type {};
struct PrivateFoo {private:void Foo() {}};
struct PublicFoo {public:void Foo() {}};
struct ProtectedFoo {protected:void Foo() {}};
struct StrangeFoo {
struct Bar { void operator()() {}; };
Bar Foo;
};
#include <iostream>
int main() {
std::cout << "PrivateFoo:" << NullaryFooCanBeCalled<PrivateFoo>::value << "\n";
std::cout << "PublicFoo:" << NullaryFooCanBeCalled<PublicFoo>::value << "\n";
std::cout << "ProtectedFoo:" << NullaryFooCanBeCalled<ProtectedFoo>::value << "\n";
std::cout << "StrangeFoo:" << NullaryFooCanBeCalled<StrangeFoo>::value << "\n";
}
On the other hand, compiler support is poor for this language quirk.
Clang 3.2 compiles and works. gcc 4.7.2 fails to build. Intel 13.0.1 compiles but returns the wrong values (true in every case!)