Why this code (fnc value in class M) do not get resolved by SFINAE rules? I'm getting an error:
Error 1 error C2039: 'type' : is not a member of
'std::tr1::enable_if<_Test,_Type>'
Of course type is not a member, it isn't defined in this general ver of enable_if but isn't the whole idea behind this to enable this ver of fnc if bool is true and do not instantiate it if it's false? Could please someone explain that to me?
#include <iostream>
#include <type_traits>
using namespace std;
template <class Ex> struct Null;
template <class Ex> struct Throw;
template <template <class> class Policy> struct IsThrow;
template <> struct IsThrow<Null> {
enum {value = 0};
};
template <> struct IsThrow<Throw> {
enum {value = 1};
};
template <template <class> class Derived>
struct PolicyBase {
enum {value = IsThrow<Derived>::value};
};
template<class Ex>
struct Null : PolicyBase<Null> { };
template<class Ex>
struct Throw : PolicyBase<Throw> { } ;
template<template< class> class SomePolicy>
struct M {
//template<class T>
//struct D : SomePolicy<D<T>>
//{
//};
static const int ist = SomePolicy<int>::value;
typename std::enable_if<ist, void>::type value() const
{
cout << "Enabled";
}
typename std::enable_if<!ist, void>::type value() const
{
cout << "Disabled";
}
};
int main()
{
M<Null> m;
m.value();
}
SFINAE does not work for non-template functions. Instead you can e.g. use specialization (of the class) or overload-based dispatching:
template<template< class> class SomePolicy>
struct M
{
static const int ist = SomePolicy<int>::value;
void value() const {
inner_value(std::integral_constant<bool,!!ist>());
}
private:
void inner_value(std::true_type) const { cout << "Enabled"; }
void inner_value(std::false_type) const { cout << "Disabled"; }
};
There is no sfinae here.
After M<Null> is known the variable ist is known also.
Then std::enable_if<ist, void> is well-defined too.
One of your function is not well-defined.
SFINAE works only for the case of template functions.
Where are template functions?
Change your code to
template<int> struct Int2Type {}
void value_help(Int2Type<true> ) const {
cout << "Enabled";
}
void value_help(Int2Type<false> ) const {
cout << "Disabled";
}
void value() const {
return value_help(Int2Type<ist>());
}
Related
Is there a way to allow two or more templates instanciations to mutually refer to each other ?
Example :
/* invalid C++ */
/* we suppose MyTemplate1 and MyTemplate2 are declared */
typedef MyTemplate1<MyInstance2> MyInstance1;
typedef MyTemplate2<MyInstance1> MyInstance2;
I suppose there is none, still asking just in case I missed something.
Adding more precision, I want to achieve such a construction :
/* invalid C++ */
#include <iostream>
template <typename typeT> struct MyStruct1 {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
typeT::print(i - 1);
}
}
};
template <typename typeT> struct MyStruct2 {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
typeT::print(i - 1);
}
}
};
/* of course this is invalid, since you can't reference MyInstance2
before it is declared */
typedef MyStruct1<MyInstance2> MyInstance1;
typedef MyStruct2<MyInstance1> MyInstance2;
int main() {
MyInstance1::print(5);
return 0;
}
output should be :
MyStruct1 : 5
MyStruct2 : 4
MyStruct1 : 3
MyStruct2 : 2
MyStruct1 : 1
MyStruct2 : 0
Please note I'm not trying to achieve a similar output, but a similar construct, where two (or more) templates instances refer to each other
with as few as possible additional code : it shall be easy to do mutual reference instantiation. However, for the implementation code of the two templates, I don't care if they are complicated.
Here's a solution that at least gives the correct output. If it's also a viable solution for your use case is not very clear though but maybe it can at least help you clarify your question a bit more.
#include <iostream>
template <template <typename> typename TemplateT> struct TemplateType {
template <typename typeT>
static void print(unsigned i) {
TemplateT<typeT>::print(i);
}
};
template <typename typeT> struct MyStruct1 {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
typeT::template print<TemplateType<MyStruct1>>(i - 1);
}
}
};
template <typename typeT> struct MyStruct2 {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
typeT::template print<TemplateType<MyStruct2>>(i - 1);
}
}
};
typedef MyStruct1<TemplateType<MyStruct2>> MyInstance1;
int main() {
MyInstance1::print(5);
return 0;
}
One way is to use class forward declaration:
template<typename T> class M
{
static int foo(int i) { return i ? T::foo(i - 1) : 0; }
};
struct A;
struct B;
struct A : M<B>{};
struct B : M<A>{};
Not same code exactly but you have recursion.
I finally found a satisfying construct, which involves using a tierce struct acting as a context to declare subs elements. It isn't forcibly the best solution for anyone, and I will probably have to adapt it a bit more to fit my very need, but here is the code :
#include <iostream>
#include <type_traits>
template <typename K, typename T> struct TypePair {
typedef K key;
typedef T type;
};
template <typename Context, typename P0, typename... PN> struct TypeMap {
template <typename K> struct get {
typedef typename std::conditional<
std::is_same<typename P0::key, K>::value,
typename P0::type::template actual<Context>,
typename TypeMap<Context, PN...>::template get<K>::type>::type type;
};
};
struct TypeNotFound {};
template <typename Context, typename P> struct TypeMap<Context, P> {
template <typename K> struct get {
typedef
typename std::conditional<std::is_same<typename P::key, K>::value,
typename P::type::template actual<Context>,
TypeNotFound>::type type;
};
};
/* defining a context to link all classes together */
template <typename... TN> struct Context {
template <typename K> struct Access {
typedef typename TypeMap<Context<TN...>, TN...>::template get<K>::type type;
};
};
/* templates we want to cross ref, note that context is passed as a parameter*/
template <typename ContextT, typename Id2> struct MyStruct1Actual {
static void print(unsigned i) {
std::cout << "MyStruct1 : " << i << std::endl;
if (i > 0) {
ContextT::template Access<Id2>::type::print(i - 1);
}
}
};
template <typename ContextT, typename Id1> struct MyStruct2Actual {
static void print(unsigned i) {
std::cout << "MyStruct2 : " << i << std::endl;
if (i > 0) {
ContextT::template Access<Id1>::type::print(i - 1);
}
}
};
/* wrappers to not have to always pass context when instancing templates */
template <typename type> struct MyStruct1 {
template <typename ContextT> using actual = MyStruct1Actual<ContextT, type>;
};
template <typename type> struct MyStruct2 {
template <typename ContextT> using actual = MyStruct2Actual<ContextT, type>;
};
/* Enum and dummy id, could simply use Enum actually, but using classes a Id
can prove to be more elegant with complex structures, expecially as it could be
used to automatically create pairs instead of having to precise Id */
enum Ids : int { Struct1, Struct2 };
template <Ids id> struct Id {};
// instancing all stuff withing context
// clang-format off
typedef Context<
TypePair< Id<Struct1>, MyStruct1< Id<Struct2> > >,
TypePair< Id<Struct2>, MyStruct2< Id<Struct1> > >
> Ctx;
// clang-format on
typedef Ctx::Access<Id<Struct1>>::type S1;
int main() {
S1::print(5);
return 0;
}
Shortening names an giving more meaning than Context or TypePair will be mandatory, but the idea is here.
Trying to accomplish the following:
// Template not necessary, but shows the pattern
template <typename T>
bool MyFunction(const T&, const uint8_t);
template <T>
struct is_myfunc_defined : std::false_type{}
// How do I properly create this
template <typname R, typename... Args>
struct is_myfunc_defined<R MyFunction(args....)> : std::true_type
{
};
struct MyStruct1 {};
struct MyStruct2 {};
// Will Match
bool MyFunction(const MyStruct&, const uint8_t){ return true; }
// Will not match
bool ShouldFail1(const MyStruct2&, const uint8_t){ return true; }
void MyFunction(const MyStruct2&, const uint8_t){ return true; }
bool MyFunction(const MyStruct2&){ return true; }
int main()
{
cout << is_myfunc_defined<MyStruct>::value << endl; // true
cout << is_myfunc_defined<MyStruct2>::value << endl; // false
}
I know how to use is_detected_exact to check for a class method with a specific return type, name, and signature, but how does one do it with a straight up function. Can't figured it out, need help.
Thanks!
I know how to use is_detected_exact to check for a class method
It's no different for a global function:
template <typename ...P>
using detect_myfunc = decltype(MyFunction(std::declval<P>()...));
template <typename T>
struct is_myfunc_defined {};
template <typename R, typename ...P>
struct is_myfunc_defined<R(P...)>
: std::experimental::is_detected_exact<R,detect_myfunc,P...> {};
{};
I am purposely using the very same title as this question because I feel that the answer that was accepted does not account for a problem that I am stuck into.
I am looking for a way to detect if some class has some member variable. It is fundamental to note that I am looking for a variable, not a member function or anything else.
Here is the example provided in the question I linked:
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { int x; };
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
But we will get the very same output if we do something like
template<typename T> struct HasX {
struct Fallback { int x; }; // introduce member name "x"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A {
void x()
{
}
};
struct B { int X; };
int main() {
std::cout << HasX<A>::value << std::endl; // 1
std::cout << HasX<B>::value << std::endl; // 0
}
(Please note that in the second example the int x in A was substituted with a member function void x()).
I have no real idea on how to work around this problem. I partially fixed this by doing something like
template <bool, typename> class my_helper_class;
template <typename ctype> class my_helper_class <true, ctype>
{
static bool const value = std :: is_member_object_pointer <decltype(&ctype :: x)> :: value;
};
template <typename ctype> class my_helper_class <false, ctype>
{
static bool const value = false;
};
template <typename T> struct HasX
{
// ...
static bool const value = my_helper_class <sizeof(f <Derived>(0)) == 2, T> :: value;
};
Which actually selects if I am using an object. However, the above doesn't work if there are more overloaded functions with the same name x in my class.
For example if I do
struct A
{
void x()
{
}
void x(int)
{
}
};
Then the pointer is not resolved successfully and the a call to HasX <A> doesn't compile.
What am I supposed to do? Is there any workaround or simpler way to get this done?
The problem is that HasX only checks if the name x exists. The ... gets selected if &C::x is ambiguous (which happens if it matches both in Fallback and T). The ChT<> overload gets selected only if &C::x is exactly Fallback::x. At no point are we actually checking the type of T::x - so we never actually check if x is a variable or function or whatever.
The solution is: use C++11 and just check that &T::x is a member object pointer:
template <class T, class = void>
struct HasX
: std::false_type
{ };
template <class T>
struct HasX<T,
std::enable_if_t<
std::is_member_object_pointer<decltype(&T::x)>::value>
>
: std::true_type { };
If &T::x doesn't exist, substitution failure and we fallback to the primary template and get false_type. If &T::x exists but is an overloaded name, substitution failure. If &T::x exists but is a non-overloaded function, substitution failure on enable_if_t<false>. SFINAE for the win.
That works for all of these types:
struct A {
void x()
{
}
void x(int)
{
}
};
struct B { int X; };
struct C { int x; };
struct D { char x; };
int main() {
static_assert(!HasX<A>::value, "!");
static_assert(!HasX<B>::value, "!");
static_assert(HasX<C>::value, "!");
static_assert(HasX<D>::value, "!");
}
I want to make function get_type_name. For types that belong to certain set example are numbers, geometry etc I want to make one get_type_name function which uses enable_if with type trait. And for each type that do not belong to particular set I want to specialize its own get_type_name function. This is my code and I get the following compiler error and can't figure out why:
error C2668: 'get_type_name': ambiguous call to overloaded function
could be 'std::string get_type_name(myenable_if::type
*)' or 'std::string get_type_name(void *)'
template<bool B, typename T = void>
struct myenable_if {};
template<typename T>
struct myenable_if<true, T> { typedef void type; };
template<class T>
struct is_number
{
static const bool value = false;
};
template<>
struct is_number<int>
{
static const bool value = true;
};
template<class T>
std::string get_type_name(void* v=0);
//get_type_name for specific type
template<>
std::string get_type_name<std::string>(void*)
{
return std::string("string");
}
//get_type_name for set of types
template<class T>
std::string get_type_name(typename myenable_if<is_number<T>::value>::type* t=0)
{
return std::string("number");
}
int main()
{
std::string n = get_type_name<int>();
}
Here is a working version.
#include <iostream>
#include <string>
#include <vector>
#include <iostream>
template<bool B, typename T = void>
struct myenable_if {};
template<typename T>
struct myenable_if<true, T> { typedef T type; };
template<class T>
struct is_number
{
static const bool value = false;
};
template<>
struct is_number<int>
{
static const bool value = true;
};
template<class T>
std::string get_type_name_helper(void* t, char)
{
return "normal";
}
template<class T>
typename myenable_if<is_number<T>::value, std::string>::type get_type_name_helper(void* t, int)
{
return "number";
}
//get_type_name for specific type
template<>
std::string get_type_name_helper<std::string>(void* t, char)
{
return std::string("string");
}
template <class T>
std::string get_type_name(void* t = 0)
{
return get_type_name_helper<T>(t, 0);
}
int main() {
std::string n = get_type_name<int>();
std::cout << n << '\n';
n = get_type_name<std::string>();
std::cout << n << '\n';
n = get_type_name<float>();
std::cout << n << '\n';
return 0;
}
See Live Demo
basicly what i want to do is written in code. so , is there a way with templates or with something else get outer class name in global function ? is there a way to get this code work?
#include <iostream>
class A
{
public:
enum class B
{
val1,
val2
};
typedef B InnerEnum;
static void f(InnerEnum val)
{
std::cout << static_cast<int>(val);
}
};
template <typename T1>
void f(typename T1::InnerEnum val)
{
T1::f(val);
}
int main()
{
A::InnerEnum v = A::InnerEnum::val1;
f(v);
return 0;
}
You may create trait for that and manually feed it:
template <typename T>
struct outer_class;
template <>
struct outer_class<A::B> { using type = A;};
And then
template <typename E>
void f(E val)
{
using T = typename outer_class<E>::type;
T::f(val);
}