【问题标题】:Template function with type thats missing (unused in run-time) function缺少类型的模板函数(在运行时未使用)函数
【发布时间】:2014-07-08 09:32:03
【问题描述】:

假设我有这样的模板函数

template <typename T> bool func(T a)
{
  if(a.X())
    return a.Y();
  return false;
}

现在我用作该函数参数的每个类都有函数 X(), 但并非我用作参数的每个类都具有函数 Y()。 但是,如果函数 a.X() 返回 true,那么我保证给定的类具有函数 Y()。我可以以某种方式编译这段代码吗,因为我知道编译器抱怨某些类型丢失的函数 Y() 永远不会被调用?这个函数实际上非常大,而且使用的类型很多,所以做一些专门化是不切实际的。

【问题讨论】:

  • 这只有在T::X() 可以在编译时评估并且a 在编译时已知,但涉及一些模板bla bla 时才有效。请澄清是否是这种情况!如果不是这种情况,那么您无法在编译时检测到 T::X() 返回 true,但 T::Y() 不存在的情况。但是,您可以在运行时强制执行此操作。
  • if (a) return b; return false; 是一种复杂的写法return a and b;

标签: c++ templates


【解决方案1】:

SFINAE 可能会有所帮助,例如:(https://ideone.com/XmjQY8)

#include <type_traits>
#include <cstdint>

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
    template <typename U>                                                   \
    class traitsName                                                        \
    {                                                                       \
    private:                                                                \
        template<typename T, T> struct helper;                              \
        template<typename T>                                                \
        static std::uint8_t check(helper<signature, &funcName>*);           \
        template<typename T> static std::uint16_t check(...);               \
    public:                                                                 \
        static                                                              \
        constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
    }

DEFINE_HAS_SIGNATURE(has_X, T::X, bool (T::*)());
DEFINE_HAS_SIGNATURE(has_Y, T::Y, bool (T::*)());

template <typename T>
typename std::enable_if<has_X<T>::value && has_Y<T>::value, bool>::type
func(T a)
{
  if(a.X())
    return a.Y();
  return false;
}

template <typename T>
typename std::enable_if<!has_X<T>::value || !has_Y<T>::value, bool>::type
func(T /*a*/)
{
    return false;
}

【讨论】:

  • 好吧,这看起来像答案 - 我不知道 type_traits 是什么以及那里到底发生了什么,但我会研究它
【解决方案2】:

这是另一个受this answer 启发的版本,它更短一些(在我的看来更好:)。

struct Action
{
    template <typename T>
    static bool func_real(T a){return func(a, special_());}

private:

    struct general_ {};
    struct special_ : general_ {};
    template<typename> struct bool_ { typedef bool type; };

    template<typename S, typename bool_<decltype(std::declval<S>().Y())>::type = 0>
    static bool func(S a, special_) {
        cout<<"Y() exists"<<endl;
        if(a.X()){
            return a.Y();
        }
        return false;
    }

    template<typename S>
    static bool func(S a, general_) {
        cout<<"Y() does not exist"<<endl;
        return false;
    }
};

Here 是现场演示。

【讨论】:

  • 不错的解决方案。试图找出类似的东西,但没有成功。你能解释一下为什么模板参数中的“= 0”有效吗?
  • @JohnB: 0false
  • @JohnB 这是为了给这个参数一个默认值,所以如果有一个正确的Y,参数将被初始化而无需明确指定它(你可以放置true或@ 987654328@ 以及 :) )。
  • 谢谢。我很困惑,因为 = 的左侧描述了一个类型,而 0 是一个值。显然,编译器不在乎?
  • 顺便说一句,我认为你不需要 bool_ 魔法。 template&lt;typename S, decltype(std::declval&lt;S&gt;().Y()) = 0&gt; 也可以。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多