Working around a possible MSVC bug when deducing multiple variadic args - c++

Here is some code that compiles in GCC (on godbolt at least - can't test locally), for handling a compile-time dependency system - the conversion operator here is to make it easier to take an entity that specifies what it can read/write and reduce it down implicitly to a more restricted form when passing into functions (please pretend that the operator below does some static_assert kind of enforcement).
template<typename... Args>
struct WriteList{};
template<typename... Args>
struct ReadList{};
template<typename Reads = ReadList<>, typename Writes = WriteList<>>
class TypedEntity;
template <typename... ReadTypes, template <typename...> typename Reads, typename... WriteTypes, template <typename...> typename Writes>
class TypedEntity<Reads<ReadTypes...>, Writes<WriteTypes...>>
{
public:
template <typename... OtherReadTypes, typename... OtherWriteTypes>
operator TypedEntity<ReadList<OtherReadTypes...>, WriteList<OtherWriteTypes...>>()
{
return {};
}
};
struct ComponentA{};
struct ComponentB{};
struct ComponentC{};
void TestFunc1(TypedEntity<ReadList<ComponentA, ComponentB>, WriteList<ComponentC>> entity)
{
}
void TestFunc2(TypedEntity<ReadList<ComponentA>, WriteList<>> entity)
{
}
void TestFunc3(TypedEntity<ReadList<ComponentA>, WriteList<ComponentC>> entity)
{
}
int main()
{
TypedEntity<ReadList<ComponentA, ComponentB>, WriteList<ComponentB>> entity;
TestFunc1(entity);
TestFunc2(entity);
TestFunc3(entity);
return 0;
}
But under MSVC (latest, i.e.g 19.28, as well as some other 19.x versions I've sampled (19.14, 19.24, etc)):
error C3547: template parameter 'OtherWriteTypes' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'TypedEntity<Reads<ReadTypes...>,Writes<WriteTypes...>>::operator TypedEntity<ReadList<OtherReadTypes...>,WriteList<OtherWriteTypes...>>'
Is this valid C++ and MSVC is wrong?
Is there a workaround for this issue in MSVC?
Appreciate it.

The error message hints at MSVC's mistake (emphasis mine):
error C3547: template parameter 'OtherWriteTypes' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'TypedEntity<Reads<ReadTypes...>,Writes<WriteTypes...>>::operator TypedEntity<ReadList<OtherReadTypes...>,WriteList<OtherWriteTypes...>>'
It's true it can't be deduced from the function parameters - but for a conversion function, deduction happens from the return type, not the empty parameter list.
So a workaround is to simplify the template signature of the conversion function. Presuming the implementation needs to know the actual ReadTypes... and WriteTypes..., the operator() definition can just call a private ordinary member function which can deduce them from parameters.
template<typename T>
struct is_WriteList_s : public std::false_type {};
template<typename... Args>
struct is_WriteList_s<WriteList<Args...>> : public std::true_type {};
template<typename T>
concept is_WriteList = is_WriteList_s<T>::value;
template<typename T>
struct is_ReadList_s : public std::false_type {};
template<typename... Args>
struct is_ReadList_s<ReadList<Args...>> : public std::true_type {};
template<typename T>
concept is_ReadList = is_ReadList_s<T>::value;
template <typename... ReadTypes, template <typename...> typename Reads,
typename... WriteTypes, template <typename...> typename Writes>
class TypedEntity<Reads<ReadTypes...>, Writes<WriteTypes...>>
{
private:
template <typename... OtherReadTypes, typename... OtherWriteTypes>
TypedEntity<ReadList<OtherReadTypes...>, WriteList<OtherWriteTypes...>>
convert_impl(std::type_identity<TypedEntity<
ReadList<OtherReadTypes...>, WriteList<OtherWriteTypes...>>>) const;
public:
template <is_ReadList OtherReadList, is_WriteList OtherWriteList>
operator TypedEntity<OtherReadList, OtherWriteList>() const
{
return convert_impl(
std::type_identity<TypedEntity<OtherReadList, OtherWriteList>>{});
}
};
I used std::type_identity just as a type-wrapper which doesn't actually have any data members or logic. If not compiling with C++20 support, any dummy template struct would do, or a raw pointer with null argument.
If using a version of MSVC or a /std: switch which does not support concepts, the concepts can be converted to SFINAE tricks or simple static_asserts.

Related

How to force SFINAE to choose the second definition of structure?

Before that I want to tell that I have tried to implement is_assignable on my own. There is no need to show me another examples - I have already seen some implementation.
I would like to fix my solution thanks to you (if it's possible, of course) that'll work out.
So, here is my code:
#include <iostream>
#include <type_traits>
#include <utility>
template<typename LambdaT>
struct is_valid_construction {
is_valid_construction(LambdaT) {}
typedef typename LambdaT lambda_prototype;
template<typename ValueTypeT, typename ExprTypeT = decltype(std::declval<lambda_prototype>()(std::declval<ValueTypeT>()))>
struct evaluate {
evaluate(ValueTypeT val) {
std::cout << "Right!";
}
typedef typename std::true_type value;
};
template<typename ValueTypeT> //The compiler ignores this definition
struct evaluate<ValueTypeT, decltype(std::declval<lambda_prototype>()(std::declval<int>()))> {
evaluate(ValueTypeT val) {
std::cout << "Nope";
}
typedef typename std::false_type value;
};
template<typename ValueTypeT>
void print_value(ValueTypeT val) {
evaluate evaluation(val);
}
};
struct ForTest {};
int main() {
is_valid_construction is_assignable([](auto x) -> decltype(x = x) { });
is_valid_construction is_less_comparable([](auto x) -> decltype(x < x) {});
is_valid_construction is_more_comparable([](auto x) -> decltype(x > x) {});
is_assignable.print_value(int{});
is_less_comparable.print_value(char{});
is_more_comparable.print_value(ForTest{});
return 0;
}
As you can see I am trying to define template structure within template structure. So, I excepted that if the invocation (with declval) of this lambda-expression with parameter of this type (rougly, in terms of substitution) is failed, then SFINAE goes further and should see that the second template definition could be convenient for instantiation. I am asking how could I fix my template structure and its default parameter to push SFINAE use the second definition?
SFINAE can be used in order to direct the compiler to choose a particular function overload, or a particular partial specialization of a class template. In the first case, substitution failures remove declarations from the overload set and in the second case, substitution failures remove the partial specialization declarations from consideration (causing either the primary template to be used, or a different partial specialization for which substitution succeeds).
But what you are trying to do here is backward: you have a situation where the primary template is potentially subject to substitution error, and you provide a partial specialization as an alternative. This can never work. Partial specialization matching begins after the template argument list to the primary template is fully known, therefore if a substitution error occurs in the primary template's template argument list, no specializations can be considered.
For example if we have
template <typename T, typename U = some_metafunction_of_T>
struct S;
template <typename T>
struct S<T, T>;
then the instantiation process of S<int> will first evaluate U for the primary template, and then, only once T and U are both known, the compiler can determine whether or not they are the same (which would allow the partial specialization to be used). If a substitution error occurs while computing U, the question of whether the partial specialization applies cannot even be asked.
To fix your code, you would have to switch the two definitions of evaluate. The primary template would have to be the "fallback", and the partial specialization would have to be potentially subject to substitution error.
as #Brian said, you should put the requirements at the primary template if the requirements are for all specializations, and put other requirements for each specialization at their own declarations:
template<typename T, typename = std::void_t</* global requirements */>>
struct S;
template<typename T>
struct S<T, std::void_t</* requirements for this specialization */>>;
and if you want one of specialization is prior to others, you can add its negative requirements to other specializations:
template<typename T, typename = std::void_t</* global requirements */>>
struct S;
template<typename T>
struct S<T, std::void_t<std::enable_if_t</* conditions for this specialization */>>>;
template<typename T>
struct S<T, std::void_t<std::enable_if_t<!/* conditions for the former specialization */>, /* requirements for this specialization */>>;
for your example, it should be like this:
template<typename Lambda>
struct is_valid_construction{
template<typename T, typename = void>
struct helper : std::false_type{};
template<typename T>
struct helper<T, std::void_t<decltype(std::declval<Lambda>()(std::declval<T>()))>> : std::true_type{};
template<typename V, typename = void>
struct evaluate;
template<typename V>
struct evaluate<V, std::enable_if_t<helper<V>::value>>;
template<typename V>
struct evaluate<V, std::void_t<std::enable_if_t<!helper<V>::value>, decltype(std::declval<Lambda>()(std::declval<int>()))>>;
};
by the way, you can use std::is_invocable to simplify this code:
template<typename Lambda>
struct is_valid_construction{
template<typename V, typename = void>
struct evaluate;
template<typename V>
struct evaluate<V, std::enable_if_t<std::is_invocable_v<Lambda, V>>>;
template<typename V>
struct evaluate<V, std::enable_if_t<!std::is_invocable_v<Lambda, V> && std::is_invocable_v<Lambda, int>>>;
};
Thanks to #RedFog and #Brian I could complete my code and I have got the such result:
#include <iostream>
#include <type_traits>
#include <utility>
template<typename LambdaT>
struct is_valid_construction {
is_valid_construction(LambdaT) {}
typedef LambdaT lambda_prototype;
template<class ValueT, class = void>
struct is_void_t_deducable : std::false_type {};
template<class ValueT>
struct is_void_t_deducable<ValueT,
std::void_t<decltype(std::declval<lambda_prototype>()(std::declval<ValueT>()))>> : std::true_type {};
template<class ValueT>
bool is_valid_for(ValueT value) {
if constexpr (is_void_t_deducable<ValueT>::value)
return true;
else
return false;
}
};
struct ForTest {};
int main() {
is_valid_construction is_assignable([](auto x) -> decltype(x * x) { });
std::cout << is_assignable.is_valid_for(0) << std::endl;
std::cout << is_assignable.is_valid_for(ForTest{});
return 0;
}
As they both said, that when I had declared template parameter like that:
template<typename ValueTypeT, typename ExprTypeT = decltype(std::declval<lambda_prototype>()(std::declval<ValueTypeT>()))>
the compiler didn't understand what a default value should the second template parameter assign and since both declarations are incompatible.
I am new one in template programming and I can try to explain the solution as simple as possible:
The second template parameter is (if to say not strictly!) should be void. So, the compiler can instantiate the template with second void parameter in two ways by means of first declaration or second declaration.
(It should be said that std::void_t<TemplateParam> becomes void if TemplateParam is well!)
If an instantiation with the second declaration is well, then the
second template parameter is void.
If an instantiation with the first declaration is well, then the
second template parameter is void.
So, we should help compiler to deduce both structures with the second template parameter void. When it tries to instantiate is_valid_for(ForTest{}) first of all it tries to deduce
std::void_t<decltype(std::declval<lambda_prototype>()(std::declval<ValueT>()))>
but gets substitution error. However, nothing prevents to deduce the second template parameter void in another way and the compilers takes the first declaration.
P.S. I know that this explanation is not good but it may help dummies like me!

How to simplify enable_if alias in template template parameter

My goal is to have a struct that takes in an alias to a specialized enable_if_t<> along with a typename variadic parameter pack and then tells me whether the enable_if's conditions were satisfied for all of the types in the pack. I have a bunch of these specialized enable_ifs, but need to write tests for them before we can put them into our open source project. I have about 2000+ lines of code manually testing these specializations, but bet I can get it to 100 or 200 if I can figure out the pattern below. I have a working version (+ godbolt link), but tbh I'm not sure why it's working and that scheme is breaking in a case where the implementation receives a parameter pack
Here is an example of the code I would like to write and it's result. I'm using C++14 and can steal basic implementations of things from C++17 likes conjunction and void_t
#include <type_traits>
#include <string>
// enable_if for arithmetic types
template <typename T>
using require_arithmetic = typename std::enable_if_t<std::is_arithmetic<T>::value>;
const bool true_arithmetic = require_tester<require_arithmetic, double, int, float>::value;
// output: true
// If any of the types fail the enable_if the result is false
const bool false_arithmetic = require_tester<require_arithmetic, double, std::string, float>::value;
// output: false
The below does do what I want, but tbf I'm not really understanding how.
// Base impl
template <template <class> class Check, typename T1, typename = void>
struct require_tester_impl : std::false_type {};
// I'm not totally sure why void_t needs to be here?
template <template <class> class Check, typename T1>
struct require_tester_impl<Check, T1, void_t<Check<T1>>> : std::true_type {};
// The recursive version (stolen conjuction from C++17)
template <template <class> class Check, typename T = void, typename... Types>
struct require_tester {
static const bool value = conjunction<require_tester_impl<Check, T>,
require_tester<Check, Types...>>::value;
};
// For the end
template <template <class> class Check>
struct require_tester<Check, void> : std::true_type {} ;
In particular, I'm not sure why the void_t is needed in the impl partial specialization for std::true_type.
What I would like to get to is a require_variadic_tester that takes in a variadic templated alias, something like enable_if<conjunction<check<T...>>::value>, and gives me true or false. Sadly, the below returns false no matter what types come in
// impl
template <template <class...> class Check, typename... Types>
struct require_variadic_impl : std::false_type {};
// Adding void_t here causes the compiler to not understand the partial specialiation
template <template <class...> class Check, typename... Types>
struct require_variadic_impl<Check, Check<Types...>> : std::true_type {};
template <template <class...> class Check, typename... Types>
struct require_variadic_tester : require_variadic_impl<Check, Types...> {};
I would like the following given the input, but can't seem to shake how to hide that conjunction one level lower
// Enable if for checking if all types are arithmetic
template <typename... Types>
using require_all_arithmetic = std::enable_if_t<conjunction<std::is_arithmetic<Types>...>::value>;
require_variadic_tester<require_all_arithmetic, double, double, double>::value;
// is true
require_variadic_tester<require_all_arithmetic, double, std::string, double>::value;
// is false
I think my failure to understand void_t in the first meta function is causing my misunderstanding
Below is the godbolt, any help in understanding this is very appreciated!
https://godbolt.org/z/8XNqpo
Edit:
To give more context in why I want the above with the conjunction inside of the enable_if_t. I'm stuck on C++14 but we are adding a new feature to our open source math library which without more generic types (and requirements on those generic types) we will end up with a ton of code bloat. We currently have stuff like this
template <int R, int C>
inline Eigen::Matrix<double, R, C> add(
const Eigen::Matrix<double, R, C>& m1, const Eigen::Matrix<double, R, C>& m2) {
return m1 + m2;
}
I'd like to have more generic templates and do something like this
template <typename Mat1, typename Mat2,
require_all_eigen<is_arithmetic, Mat1, Mat2>...>
inline auto add(Mat1&& m1, Mat2&& m2) {
return m1 + m2;
}
I have all of those require_*_<container> aliases setup, but the tests for all of those requires is about 2000+ lines and in the future that will be a funky mess to have to deal with.
We have unary and variadic template enable_if aliases, at this point the above unary case does what I want ala a nice test like
#include <gtest/gtest.h>
TEST(requires, arithmetic_test) {
EXPECT_FALSE((require_tester<require_arithmetic, std::string>::value));
EXPECT_TRUE((require_tester<require_arithmetic, double, int, float>::value));
}
The issue I have is with testing the variadic template enable_if aliases, where I want to be able to write something like
// Enable if for checking if all types are arithmetic
template <typename... Types>
using require_all_arithmetic = std::enable_if_t<conjunction<std::is_arithmetic<Types>...>::value>;
/// For the tests
TEST(requires, arithmetic_all_test) {
EXPECT_FALSE((require_variadic_tester<require_all_arithmetic, std::string,
Eigen::Matrix<float, -1, -1>>::value));
EXPECT_TRUE((require_variadic_tester<require_all_arithmetic,
double, int, float>::value));
}
If I can test all of this I think the requires part of our library alone could be a nice header only mini-library for what I'm calling "bad fake concepts in 14" (or bfc14 for short ;-))
Here's what happens with your require_tester<require_arithmetic, double, double, int>:
This doesn't match the partial specialization of require_tester, which has just two template arguments <Check, void>, so we use the primary template
template <template <class> class Check, typename T, typename... Types>
struct require_tester;
with Check = require_arithmetic; T = double; Types = double, int. It does not match the partial specialization of require_tester. Member value is the result of
conjunction<require_tester_impl<Check, T>, require_tester<Check, Types...>>::value
where the interesting part is require_tester_impl<Check, T> = require_tester_impl<require_arithmetic, double>. First, since the template parameters of require_tester_impl are
template <template <class> class Check, typename T1, typename = void>
and only two explicit template argumetns are given, we know the actual template arguments are <require_arithmetic, double, void>. Now we need to see whether or not this matches the partial specialization of require_template_impl, so we try to match:
require_template_impl<require_arithmetic, double, void>
require_template_impl<Check, T1, void_t<Check<T1>>>
So template argument deduction finds Check = require_arithmetic and T1 = double. The type void_t<Check<T1>> does not cause any deduction of Check or T1. But the deduced parameter values must be substituted in, and we find void_t<Check<T1>> is void_t<require_arithmetic<double>> is void. This does match the void from the template arguments, so the partial specialization does match, and require_template_impl<require_arithmetic, double, void> inherits std::true_type, not std::false_type.
On the other hand, if T1 were std::string instead of double, substituting the deduced template arguments in would find void_t<require_arithmetic<std::string>> is invalid, via the eventual enable_if<...>::type where no member type exists. When substituting deduced template arguments into other template parameters fails, this means the partial specialization is thrown out as not a match. So require_template_impl<require_arithmetic, std::string, void> uses the primary template and inherits std::false_type.
Going back to the value member of require_tester, it recursively finds require_tester<require_arithmetic, double, int>::value via require_tester<require_arithmetic, int>::value via require_tester<require_arithmetic>::value which is the same as require_tester<require_arithmetic, void>::value. All the value members are true, so the final value is true.
Though I would simplify this a bit:
The void is unnecessary in the require_tester recursion, and causes the strange "fact" that require_tester<Anything, void>::value is always true. It would be better to remove the = void default from the primary require_tester template, and make the base case template <template <class> class Check> require_tester<Check> instead.
Your value expression in the require_tester primary template is always giving exactly two template arguments to conjunction, so it's not really using its variadic property, and you could just as well write require_tester_impl<...>::value && require_tester<...>::value. Since require_tester is doing a recursion itself, it doesn't need the recursive definition abstracted into conjunction. Instead, require_tester could be simplified to count on conjunction and avoid doing any recursion itself:
template <template <class> class Check, typename... Types>
struct require_tester : conjunction<require_tester_impl<Check, Types>...>
{};
// No other specialization needed.
The require_variadic_tester template can follow a similar pattern, except that I'll give the dummy template parameter which was just typename = void a name, typename Enable. And it needs to come before the template parameter pack, so it's not that useful to actually default it to void, and we need to make sure to use the appropriate void template argument in the corresponding position.
template <template <class...> class Check, typename Enable, typename... Types>
struct require_variadic_impl : std::false_type {};
template <template <class...> class Check, typename... Types>
struct require_variadic_impl<Check, void_t<Check<Types...>>, Types...> : std::true_type {};
template <template <class...> class Check, typename... Types>
struct require_variadic_tester : require_variadic_impl<Check, void, Types...> {};
See the modified program on godbolt, with desired results.
Not sure to understand all your needs but...
What I would like to get to is a require_variadic_tester that takes in a variadic templated alias, something like enable_if<conjunction<check<T...>>::value>, and gives me true or false. Sadly, the below returns false no matter what types come in
Are you sure that you want conjunction<check<T...>> ?
Or do you want conjunction<check<T>...>?
I mean... the check must receive a variadic list of types or do you want to check a an alias, that (as in your example) receive a single type and a conjunction that is true iff (if and only if) the check is satisfied for all types?
In this second case, std::void_t is very handy to verify that all checks are satisfied.
I propose the following require_variadic_impl and require_variadic_tester
template <template <typename> class, typename, typename = void>
struct require_variadic_impl
: public std::false_type
{ };
template <template <typename> class C, typename ... Ts>
struct require_variadic_impl<C, std::tuple<Ts...>, std::void_t<C<Ts>...>>
: public std::true_type
{ };
template <template <typename> class C, typename ... Ts>
struct require_variadic_tester
: public require_variadic_impl<C, std::tuple<Ts...>>
{ };
Now from
template <typename T>
using require_arithmetic = typename std::enable_if_t<std::is_arithmetic<T>::value>;
// ...
printf("\nGeneric Variadic: \n\n");
const char* string_generic_var_check =
require_variadic_tester<require_arithmetic, std::string>::value ? "true" : "false";
const char* double_generic_var_check =
require_variadic_tester<require_arithmetic, double, double, double>::value ? "true" : "false";
std::printf("\t String: %s\n", string_generic_var_check);
std::printf("\t Double: %s\n", double_generic_var_check);
you get
Generic Variadic:
String: false
Double: true
think my failure to understand void_t in the first meta function is causing my misunderstanding
Try thinking std::void_t<Ts...> as "enable if all Ts are enabled".
template <template <class> class Check, typename T1, typename = void>
struct require_tester_impl : std::false_type {};
// I'm not totally sure why void_t needs to be here?
template <template <class> class Check, typename T1>
struct require_tester_impl<Check, T1, void_t<Check<T1>>> : std::true_type {};
Here, you required the third parameter of require_tester_impl is of type void, since you wrote it as default value. If the user, when specializing require_tester_impl doesn't specify its third parameter, it is void. So the compiler will search for a partial specialization where the first template parameter is a unary class template, the second template parameter is a type, and the third one is void, otherwise, no partial specialization will be found, since the third parameter of any partial specialization will fail.
That's where void_t comes into play. Since you want to inject Check into the parameter, but you require void, that's when void_t comes handy, since every type used to specialized it is mapped to void, which is what you really need. When the partial specialization doesn't fail, you will have two enabled specializations, the default one, and the partial one.
The partial one will be finally choosen since it is more specialized than the other, since void have been calculated in a way dependant on other template parameters.
That's for the first part. For the second part (the variadic template), remember that, if enable_if succeds, it returns void.
So your require_variadic_impl:
template <template <class...> class Check, typename... Types>
struct require_variadic_impl : std::false_type {};
// Adding void_t here causes the compiler to not understand the partial specialiation
template <template <class...> class Check, typename... Types>
struct require_variadic_impl<Check, Check<Types...>> : std::true_type {};
have a problem here, and it's that, Check<Types...>, since it is aliased to enable_if, returns void when it success, however, the second parameter of require_variadic_impl is not void so the partial specializations finally fails when the check is correct. When it isn't, then the enable_if have no inner type defined,the partial specialization also fails, and the base case is used again.
However, do it simple. I propose here a much more readable implementation with same final result:
#include <iostream>
#include <type_traits>
#include <string>
template<class... Ts>
struct require_all_arithmetic : std::conjunction<std::is_arithmetic<Ts>...>
{};
template<template<class...> class Check, class... Ts>
struct require_variadic_tester : Check<Ts...>
{};
int main()
{
std::cout << require_variadic_tester<require_all_arithmetic, double, double, double>::value << std::endl;
std::cout << require_variadic_tester<require_all_arithmetic, double, std::string, double>::value << std::endl;
}
https://coliru.stacked-crooked.com/a/f9fb68e04eb0ad40
Or just:
#include <iostream>
#include <type_traits>
#include <string>
template<class... Ts>
struct require_all_arithmetic : std::conjunction<std::is_arithmetic<Ts>...>
{};
int main()
{
std::cout << require_all_arithmetic<double, double, double>::value << std::endl;
std::cout << require_all_arithmetic<double, std::string, double>::value << std::endl;
}
However, if you require a check that is sfinae-friendly, plus a struct that maps "sfinae"-friendly checks to true/false, you can use constexpr methods instead. It's much more simple:
template<class... Ts>
using require_all_arithmetic = std::enable_if_t<std::conjunction<std::is_arithmetic<Ts>...>::value>;
template<template<class...> class Check, class... Ts, class = Check<Ts...> >
constexpr bool require_variadic_tester_impl(int)
{ return true; }
template<template<class...> class Check, class... Ts>
constexpr bool require_variadic_tester_impl(unsigned)
{ return false; }
template<template<class...> class Check, class... Ts>
struct require_variadic_tester
{ static constexpr bool value = require_variadic_tester_impl<Check, Ts...>(42); };
int main()
{
std::cout << require_variadic_tester<require_all_arithmetic, double, double, double>::value << std::endl;
std::cout << require_variadic_tester<require_all_arithmetic, double, std::string, double>::value << std::endl;
}
The technique works as follow: if Check fails, only the second overload will compile, which returns false. However, if the check is valid and the inner enable_if is defined, then both overloads will be valid but, since you have passed an int (42), and the second overload receives an unsigned, the first overload will be a better match, returning true.
https://coliru.stacked-crooked.com/a/bfe22ea099dd5749
Finally, if you want the check always is true_type or false_type, then, instead of inheriting, you can just alias std::conditional:
template<template<class...> class Check, class... Ts>
using require_variadic_tester =
std::conditional_t<require_variadic_tester_impl<Check, Ts...>(42),
std::true_type, std::false_type>;

Generic `Is_enabled` SFINAE structure

I aim to implement a structure template that can be used to detect either if a template substitution is well formed or will fail. An example of usage is to provide two versions of template functions depending on whether the template parameter is comparable or not.
It can be solved quite easily if one provides structures for each scenario explicitly, e.g. whether there exists an equality operator for the template type, as shown here. But I failed to implement a structure that would accept (almost) arbitrary construct as a template argument.
The "best" approach I have reached so far uses template template argument. It compiles, but it does not fit the case when the argument substitution should be well formed.
#include <iostream>
#include <type_traits>
template <typename T = void, typename...>
using Enable = T;
template <bool Cond, typename T = void>
using Enable_if = typename std::enable_if<Cond, T>::type;
template <typename T, template<typename> class X, typename = void>
struct Is_enabled : std::false_type {};
template <typename T, template<typename> class X>
struct Is_enabled<T, X, Enable<X<T>>> : std::true_type {};
/// An example of construct
template <typename T>
using Equals = decltype(std::declval<T>() == std::declval<T>());
template <typename T>
using Enabled_eq = Enable_if<Is_enabled<T, Equals>::value>;
template <typename T>
using Disabled_eq = Enable_if<!Is_enabled<T, Equals>::value>;
template <typename T>
Enabled_eq<T> foo()
{
std::cerr << "enabled!" << std::endl;
}
template <typename T>
Disabled_eq<T> foo()
{
std::cerr << "disabled!" << std::endl;
}
struct A {};
int main(int /*argc*/, const char* /*argv*/[])
{
foo<int>(); /// should print "enabled!"
foo<A>(); /// should print "disabled!"
return 0;
}
In case of int, it should obviously print "enabled!", and in case of A it should print "disabled!". But it always prints "disabled!", so the specialization of Is_enabled is never done.
Am I somewhat close to a correct solution, or will it be more complicated?
The third template parameter of Is_enabled defaults to void. This is what the compiler will use in the Is_enabled<T, Equals> instantiation. That is, Is_enabled<T, X, Enable<X<T>>> : std::true_type {}; can be used only if Enable<X<T>> evaluates to void. By explicitly passing a template argument X<T> to class template Enable declared as:
template <typename T = void, typename...>
using Enable = T;
you actually create an alias for X<T> itself, and the void type (the default one, needed for the dispatching to work) is not used at all. In your case, X<T> is the result of the decltype specifier. For foo<A>() it does lead to instantiation failure. For foo<int>(), however, you get the result type of integers comparison which is bool. That is, although there is no subsitution failure, the compiler cannot use the class template specialization, because it is specialized for void, not bool.
In order to fix the code, you should rewrite Enable to always result with void:
template <typename...>
using Enable = void;
This is also known as std::void_t.

Concept to check for variadic template function

With C++20 and concepts around the corner I wondered if it will be possible to write a concept to check if a Type has a function with a certain name which takes any number of arbitrary arguments.
Take the following code for example (with GCC's current concept TS syntax):
template <typename T>
concept bool Initializable = requires(T t) {
{ t.init() } ->void;
};
struct S {
void init() {}
};
static_assert(Initializable<S>);
The concept Initializable checks if a Type implements a void init() function. Now lets assume there is another Type which also has an init function but one which requires arguments, e.g. an int:
struct T {
void init(int) {}
};
Now in this case the static assertion would fail.
Is there any way to make the Initializable concept ignore the function arguments? This example might seem rather derived, but for something like a generic serializer there might be use-cases for such a concept.
There is a type trait for that, std::is_member_function_pointer. But if you want that the return type is void too, then you can do both at the same time:
template <typename>
struct mptr_returns_void : std::false_type {};
template <typename T, typename ...Args>
struct mptr_returns_void<void(T::*)(Args...)> : std::true_type {};
template <typename T>
concept Initializable = mptr_returns_void<decltype(&T::init)>::value;

Why can't C++ infer the template type?

Why can't the compiler figure out these template parameters? Is there a way to make it do so?
(I'm using Visual Studio 2010.)
template<typename T, typename TFunc>
void call(TFunc func) { func(T()); }
void myfunc(void *) { }
int main() { call(myfunc); }
T appears nowhere in the parameter list so T cannot be deduced from the function arguments. All types to be deduced must appear in deduced contexts in the parameter list. For example,
template <typename TReturn, typename TParameter>
void call(TReturn (*f)(TParameter))
{
f(TParameter());
}
Template parameter deduction for function templates only works based on function arguments, nothing else. The function definition is never looked at for the purpose of determining the template parameters, so your parameter T cannot possibly be deduced.
You could remedy your situation by incorporating the type into the function signature: Since you expect the outer function to be called with a function itself, make that explicit:
template <typename T> void foo(void(*f)(T))
{
T x;
f(x);
// ...
}
Combine function overloading with functors, and it becomes impossible in the general case to determine what arguments can be passed to a callable entity.
Consider, for example
struct FunctorExample {
void operator()(int x) {...}
std::string operator()(const std::string& ) {...}
};
If there were some way to coax the compiler to pattern match on arguments, it would have to have undefined or error behavior when applied to FunctorExample.
Instead, the trend seems to be that when you want to template metaprogram with functors, you specify the functor and argument list. Examples (off the top of my head) being boost::result_of and boost::fusion.
Edit: That said, if you're willing to restrict your attention somewhat, and you can use some C++11 syntax (decltype), you can arrange to introspect a bit more:
// Support functors with a very simple operator():
template <typename T> struct argument :
public argument<decltype(&T::operator())> {};
// Pointers to member functions
template <typename C, typename R, typename A> struct argument<R(C::*)(A)>
{typedef A type;};
// Function types
template <typename R, typename A> struct argument<R(A)> {typedef A type;};
// Function pointer types.
template <typename R, typename A> struct argument<R(*)(A)> {typedef A type;};
// Now for call:
template <typename FuncType>
void call(FuncType func) {
typedef typename argument<FuncType>::type Arg;
func(Arg());
}
// example:
class FunctorInt {public: int operator()(int ) {return 0;};};
void myfunc(void *) {}
int main() {
call(myfunc);
call(FunctorInt());
}
Variadic templates could be used to expand this stuff to support more than one argument.