Notice the difference between ApplyIndexForConstexpr and ApplyIndexForConstexprElse.
SFINAE works if there's a signature match;
`ApplyIndexForConstexpr` generates 2 explicit template instance while
`ApplyIndexForConstexprElse` generates single explicit template instance.
#include <functional>
#include <iostream>
#include <optional>
template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexForConstexpr(F f) {
if constexpr(sizeof(F) == 1){
return I;
}
if constexpr(I - 1 == 0){
return std::nullopt;
} else {
return ApplyIndexForConstexpr<I-1>(f);
}
}
template <size_t I, typename F>
constexpr std::optional<int> ApplyIndexForConstexprElse(F f) {
if constexpr(sizeof(F) == 1){
return I;
} else if constexpr(I - 1 == 0){
return std::nullopt;
} else {
return ApplyIndexForConstexpr<I-1>(f);
}
}
int main() {
auto run = []{};
ApplyIndexForConstexpr<2>(run);
ApplyIndexForConstexprElse<2>(run);
}
Generated code:
#include <functional>
#include <iostream>
#include <optional>
template<size_t I, typename F>
inline constexpr std::optional<int> ApplyIndexForConstexpr(F f)
{
if constexpr(sizeof(F) == 1) {
return std::optional<int>(I);
}
if constexpr((I - 1) == 0) {
return std::optional<int>(std::nullopt_t(std::nullopt));
} else /* constexpr */ {
return ApplyIndexForConstexpr<I - 1>(f);
}
}
/* First instantiated from: insights.cpp:31 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline constexpr std::optional<int> ApplyIndexForConstexpr<2, __lambda_30_13>(__lambda_30_13 f)
{
if constexpr(true) {
return std::optional<int>(2UL);
}
if constexpr(false) {
} else /* constexpr */ {
return ApplyIndexForConstexpr<2UL - 1>(__lambda_30_13(f));
}
}
#endif
/* First instantiated from: insights.cpp:14 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline constexpr std::optional<int> ApplyIndexForConstexpr<1, __lambda_30_13>(__lambda_30_13 f)
{
if constexpr(true) {
return std::optional<int>(1UL);
}
if constexpr(true) {
return std::optional<int>(std::nullopt_t(std::nullopt));
} else /* constexpr */ {
}
}
#endif
template<size_t I, typename F>
inline constexpr std::optional<int> ApplyIndexForConstexprElse(F f)
{
if constexpr(sizeof(F) == 1) {
return std::optional<int>(I);
} else /* constexpr */ {
if constexpr((I - 1) == 0) {
return std::optional<int>(std::nullopt_t(std::nullopt));
} else /* constexpr */ {
return ApplyIndexForConstexpr<I - 1>(f);
}
}
}
/* First instantiated from: insights.cpp:32 */
#ifdef INSIGHTS_USE_TEMPLATE
template<>
inline constexpr std::optional<int> ApplyIndexForConstexprElse<2, __lambda_30_13>(__lambda_30_13 f)
{
if constexpr(true) {
return std::optional<int>(2UL);
} else /* constexpr */ {
}
}
#endif
int main()
{
class __lambda_30_13
{
public:
inline /*constexpr */ void operator()() const
{
}
using retType_30_13 = auto (*)() -> void;
inline constexpr operator retType_30_13 () const noexcept
{
return __invoke;
};
private:
static inline /*constexpr */ void __invoke()
{
__lambda_30_13{}.operator()();
}
public:
// inline /*constexpr */ __lambda_30_13(const __lambda_30_13 &) noexcept = default;
};
__lambda_30_13 run = __lambda_30_13{};
ApplyIndexForConstexpr<2>(__lambda_30_13(run));
ApplyIndexForConstexprElse<2>(__lambda_30_13(run));
return 0;
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.