C++中函数变体的多种类型的开关情况下的案例数量限制

huangapple go评论69阅读模式
英文:

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&lt;unsigned int N&gt;
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&lt;&gt; class WrappedUInt&lt;0&gt; : public std::false_type {};
template&lt;&gt; class WrappedUInt&lt;1&gt; : public std::true_type {};

Then I have defined a variant type for an aplicattion:

using wuint_64_variant = std::variant&lt;
    WrappedUInt&lt;0&gt;,WrappedUInt&lt;1&gt;,WrappedUInt&lt;2&gt;,WrappedUInt&lt;3&gt;,WrappedUInt&lt;4&gt;,WrappedUInt&lt;5&gt;,
    // to complete this large list with step 1
    WrappeUInt&lt;60&gt;,WrappeUInt&lt;61&gt;,WrappeUInt&lt;62&gt;,WrappeUInt&lt;63&gt;
&gt;;

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&lt;int&gt;&amp; value) {
        cout &lt;&lt; &quot;The Try contained the value &quot; &lt;&lt; value.get() &lt;&lt; endl;
    },
    [](const TryFailure&amp; fail) {
        cout &lt;&lt; &quot;Try Try contained a failure&quot;
    });

Definition

#pragma once
#include &lt;variant&gt;

namespace core {
inline namespace utility {

template&lt;class... Ts&gt;
struct overloaded : Ts... {
    using Ts::operator()...;
};

template&lt;class... Ts&gt;
overloaded(Ts...) -&gt; overloaded&lt;Ts...&gt;;

/// 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&lt;int&gt;&amp; value) {
///         cout &lt;&lt; &quot;The Try contained the value &quot; &lt;&lt; value.get() &lt;&lt; endl;
///     },
///     [](const TryFailure&amp; fail) {
///         cout &lt;&lt; &quot;Try Try contained a failure&quot;
///     });
/// ```
///
/// \endverbatim
///
template&lt;class T, class... Us&gt;
auto match(T&amp;&amp; variant, Us&amp;&amp;... handlers) {
    return std::visit(overloaded{std::forward&lt;Us&gt;(handlers)...}, std::forward&lt;T&gt;(variant));
}

}; // utility
}; // core

huangapple
  • 本文由 发表于 2023年5月6日 22:21:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76189394.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定