英文:
The limits of number of cases of a switch in C++ for functions variants with many types
问题
I have coded a class:
template<unsigned int N>
class WrappedUInt {
unsigned int m_value;
public:
// Many methods to imitate the unsigned integer type
// This class works as an interface (except for `N==0 || N==1`)
};
template<> class WrappedUInt<0> : public std::false_type {};
template<> class WrappedUInt<1> : public std::true_type {};
Then I have defined a variant type for an application:
using wuint_64_variant = std::variant<
WrappedUInt<0>, WrappedUInt<1>, WrappedUInt<2>, WrappedUInt<3>, WrappedUInt<4>, WrappedUInt<5>,
// to complete this large list with step 1
WrappedUInt<60>, WrappedUInt<61>, WrappedUInt<62>, WrappedUInt<63>
>;
Now I need functions for this variant type. I use a switch/case statement to work with this. It works well with 2, 3, 4, ..., 63 distinct cases in the statement.
I have read that the g++ compiler has limited the number of cases to 200, as clang++, MSVC, and Intel compilers to 256, and the recommendation of the standard is a minimum of 16384.
But gcc fails with more than 63 cases plus the default case, with the error 'File too big'. Why?
And another question is, can I increment the number of cases permitted in a switch statement?
英文:
I have coded a class:
template<unsigned int N>
class WrappedUInt {
unsigned int m_value;
public:
// Many methods to imitate the unsigned integer type
// This class works as a interface (except for `N==0 || N==1`)
};
template<> class WrappedUInt<0> : public std::false_type {};
template<> class WrappedUInt<1> : public std::true_type {};
Then I have defined a variant type for an aplicattion:
using wuint_64_variant = std::variant<
WrappedUInt<0>,WrappedUInt<1>,WrappedUInt<2>,WrappedUInt<3>,WrappedUInt<4>,WrappedUInt<5>,
// to complete this large list with step 1
WrappeUInt<60>,WrappeUInt<61>,WrappeUInt<62>,WrappeUInt<63>
>;
Now I need functions for this variant type. I use a switch/case statement to work with this. It works very pretty with 2, 3, 4, ... , 63 distint cases in the statement.
I have read that the g++ compiler has limited the number of cases to 200, as clang++, MSVC and Intel compilers to 256, and the recomendation of standard is a minimum of 16384.
But gcc fails with more than 63 cases plus the default case, with the error 'File too big', why?
And other question is can I increment the number of cases permitted in a switch statement?
答案1
得分: 1
I agree with @JaMIT that this is unlikely due to a compiler switch statement limitation. Also mentioned by @user17732522 in the comments, if you have a std::variant
, there are more efficient options for dispatching. The following match
function allows you to write readable and efficient code for dispatching on type (including auto as a catch-all) for a std::variant
.
Use
match(try_value,
[](const TrySuccess<int>& value) {
cout << "The Try contained the value " << value.get() << endl;
},
[](const TryFailure& fail) {
cout << "Try Try contained a failure";
});
Definition
#pragma once
#include <variant>
namespace core {
inline namespace utility {
template<class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
/// Pattern match a `std::variant` derived type against its contained type.
///
/// \tparam T The variant type
/// \tparam Us... The lambda types
///
/// \verbatim embed:rst:leading-slashes
///
/// ```{code-block} cpp
/// match(try_value,
/// [](const TrySuccess<int>& value) {
/// cout << "The Try contained the value " << value.get() << endl;
/// },
/// [](const TryFailure& fail) {
/// cout << "Try Try contained a failure";
/// });
/// ```
///
/// \endverbatim
///
template<class T, class... Us>
auto match(T&& variant, Us&&... handlers) {
return std::visit(overloaded{std::forward<Us>(handlers)...}, std::forward<T>(variant));
}
}; // utility
}; // core
英文:
I agree with @JaMIT that this is unlikely due to a compiler switch statement limitation. Also mentioned by @user17732522 in the comments, if you have a std::variant
, there are more efficient options for dispatching. The following match
function allows you to write readable and efficient code for dispatching on type (including auto as a catch-all) for a std::variant
.
Use
match(try_value,
[](const TrySuccess<int>& value) {
cout << "The Try contained the value " << value.get() << endl;
},
[](const TryFailure& fail) {
cout << "Try Try contained a failure"
});
Definition
#pragma once
#include <variant>
namespace core {
inline namespace utility {
template<class... Ts>
struct overloaded : Ts... {
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
/// Pattern match a `std::variant` derived type against its contained type.
///
/// \tparam T The variant type
/// \tparam Us... The lambda types
///
/// \verbatim embed:rst:leading-slashes
///
/// ```{code-block} cpp
/// match(try_value,
/// [](const TrySuccess<int>& value) {
/// cout << "The Try contained the value " << value.get() << endl;
/// },
/// [](const TryFailure& fail) {
/// cout << "Try Try contained a failure"
/// });
/// ```
///
/// \endverbatim
///
template<class T, class... Us>
auto match(T&& variant, Us&&... handlers) {
return std::visit(overloaded{std::forward<Us>(handlers)...}, std::forward<T>(variant));
}
}; // utility
}; // core
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论