【问题标题】:SFINAE check if expression compiles and return std::true_type [duplicate]SFINAE 检查表达式是否编译并返回 std::true_type [重复]
【发布时间】:2014-06-26 04:37:23
【问题描述】:

如果以下表达式编译,我想得到 std::true_type:

template<typename T>
static constexpr std::true_type check(T*) ??????
std::declval<T>().func_name( std::declval<Args>()... ) // method to check for

和 std::false_type 否则我通常会这样做

template<typename>
static constexpr std::false_type check(...);

我搜索类似 enable_if 的东西,如果表达式编译,它会返回一个常量类型。看起来很简单,但让我头疼:-)

【问题讨论】:

  • decltype(std::declval&lt;T&gt;().func_name( std::declval&lt;Args&gt;()... ), void(), std::true_type{})
  • @Klaus 那些是operator, 不是多个参数。
  • @Klaus decltype 仅计算变量的 DECLared TYPE,或者,如果 () 中的内容不是变量,则计算为 () 中的表达式类型。在这里,表达式是something, void(), std:true_type{}。这是由逗号运算符分隔的三个表达式。最后两个是“功能符号中的强制转换”,它们创建临时/值。 void() 创建 void 类型的值,std::true_type{} 创建 std::true_type 类型的临时值。逗号运算符计算所有表达式,但仅“返回”最右边的表达式。
  • OK,发现这里只是简单的用来获取最后一个表达式的类型。但是为什么中间有一个 ..., void(), ... 呢?那只是为了好玩吗?很高兴了解这一点:-) 谢谢!
  • 这是为了打破可能超载的operator,void 类型的参数不能重载,因此 expr0, void(), expr1 始终使用内置逗号运算符。

标签: c++ c++11 sfinae


【解决方案1】:

我个人使用它(使用完整签名):

#include <cstdint>

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)               \
    template <typename U, typename... Args>                                 \
    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_func_name, T::func_name, void (T::*)(Args...));

然后像这样测试它:

struct C
{
    void func_name(char, int);
};

static_assert(has_func_name<C, char, int>::value, "unexpected non declared void C::func_name(char, int)");
static_assert(!has_func_name<C, int, int>::value, "unexpected declared void C::func_name(int, int)");

【讨论】:

    猜你喜欢
    • 2011-01-08
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2021-03-16
    • 2012-05-14
    • 2016-10-01
    • 1970-01-01
    相关资源
    最近更新 更多