Consider the following code:
#include <iostream>
enum class E
{
A,
B
};
template<E e> int f();
template<> int f<E::A>(){ return 1; }
template<> int f<E::B>(){ return 2; }
int main()
{
for( const E i : {E::A, E::B} )
{
std::cout << f<i>() << "\n";
}
}
This fails to compile, because i is not initialised with a constant expression. Is it possible make this idea of a code work?
This is very related: Why isn't a for-loop a compile-time expression? .
i
in your loop is not a constant expression. However, by stealing from this answer one can make your code call f<i>
inside the loop. It is not directly what you asked for because the proposed solution is for size_t
index based loops instead of iterators, but it does call f<i>
for all values of the enum:
#include <iostream>
#include <utility>
// your code
enum class E
{
A,
B
};
template<E e> int f();
template<> int f<E::A>(){ return 1; }
template<> int f<E::B>(){ return 2; }
// https://stackoverflow.com/a/47563100/4117728
template<std::size_t N>
struct num { static const constexpr auto value = N; };
template <class F, std::size_t... Is>
void for_(F func, std::index_sequence<Is...>)
{
using expander = int[];
(void)expander{0, ((void)func(num<Is>{}), 0)...};
}
template <std::size_t N, typename F>
void for_(F func)
{
for_(func, std::make_index_sequence<N>());
}
// emulate constexpr for (size_t i=0;i<2;++i) f<i>();
int main()
{
for_<2>([&] (auto i) {
std::cout << f<static_cast<E>(decltype(i)::value)>();
});
}
Output :
12
Probably there is a simpler solution for your actual problem. The answer to your literal question is: No. You cannot call f<i>
when i
is not a compile time constant. For detailed explanation I refer you to the above mentioned q&a.
The compiler is not able to deduce i in the call to f<i>()
. This is because compilation happens before runtime, and the value of i is only available during runtime. You can work around this by adding a translator.
#include <iostream>
enum class E
{
A,
B
};
template<E e> int f();
template<> int f<E::A>(){ return 1; }
template<> int f<E::B>(){ return 2; }
int bar(E e)
{
int retval = 0;
switch(e)
{
case E::A:
{
return f<E::A>();
break;
}
case E::B:
{
return f<E::B>();
break;
}
default:
{
break;
}
}
return retval;
}
int main()
{
for( const E i : {E::A, E::B} )
{
std::cout << bar(i) << "\n";
}
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.