Seriously, you need to build a thorough foundation before trying so much complicated code. I gave you an elaborate explanation in your last thread, and I hope the explanations sticks to the point that you recognize the same problem wearing different pajamas, but you aren't going to recognize the issues with complicated code in the future if you don't understand the point of failure.
Hm, I guess you have a point... I'll consider to slow down a little bit in the future, sorry
By the way, for the ones interested in the problem: I managed to solve it. I'll post the code below for reference.
First thing to do was to define some concept traits:
Code:
struct concept {
};
template<typename Type>
struct incrementable: public concept {
template<typename T=Type>
auto operator()() -> decltype(++std::declval<T&>());
};
template<typename First, typename Second=First>
struct comparable: public concept {
template<typename F=First, typename S=Second>
auto operator()() -> decltype(std::declval<F&>()==std::declval<S&>());
};
Next, a feature that allows one to convert them into a compile-time boolean:
Code:
template<typename, typename=void>
struct model: public std::false_type {
};
template<typename Concept>
struct model<Concept, void_t<decltype(Concept{}())>>: public std::true_type {
};
And last, some functionality to achieve the intended look of concept handling:
Code:
template<typename First, typename Second=void, typename... Types>
struct check {
using type=typename std::enable_if<model<First>::value,
typename check<Second, Types...>::type>::type;
};
template<typename Type>
struct check<Type,
typename std::enable_if<std::is_base_of<concept, Type>::value>::type> {
using type=typename std::enable_if<model<Type>::value>::type;
};
template<typename Type>
struct check<Type,
typename std::enable_if<!std::is_base_of<concept, Type>::value>::type> {
using type=Type;
};
template<typename... Types>
using trait=typename check<Types...>::type;
Well, honestly I didn't think it would be that little code, but as it works I'm satisfied. One can use it the following way:
Code:
template<typename Type>
auto increment(Type& value) -> trait<incrementable<Type>> // evaluates to void
{
++value;
}
template<typename First, typename Second=First>
auto compare(const First& left, const Second& right)
-> trait<comparable<First, Second>, bool> // evaluates to bool
{
return (left==right);
}
template<typename First, typename Second=First>
auto increment_and_compare(First& left, const Second& right)
-> trait<incrementable<First>, comparable<First, Second>, bool> // evaluates to bool
{
++left;
return (left==right);
}
int main()
{
std::cout << model<incrementable<int>>() << std::endl; // prints 1
std::cout << model<incrementable<const int>>() << std::endl; // prints 0
std::cout << model<comparable<int, const int>>() << std::endl; // prints 1
std::cout << model<comparable<int*, const int>>() << std::endl; // prints 0
{
auto value=0;
increment(value); // fine
}
{
const auto value=0;
increment(value); // error
}
increment(33); // error
std::cout << compare(true, false) << std::endl; // prints 0
std::cout << compare('a', 'a') << std::endl; // prints 1
std::cout << compare('a', "abc") << std::endl; // error
{
auto first=0, second=1;
std::cout << increment_and_compare(first, second) << std::endl; // prints 1
}
{
const auto first=0, second=1;
std::cout << increment_and_compare(first, second) << std::endl; // error
}
}
Well, that's it. Thanks for your assistance!