【问题标题】:Add compile-error messages to SFINAE macro将编译错误消息添加到 SFINAE 宏
【发布时间】:2013-03-03 15:45:59
【问题描述】:

我在玩SFINAE,但我试图在处理宏生成的代码时获取一些有意义的编译器错误信息。我使用THIS answer 来运行以下命令: (我想用 member_test(a) 检查 Type A 是否有一些之前定义的成员)

//Check for member variable with given name.
#define CREATE_MEMBER_VAR_CHECK(var_name)                                   \
                                                                            \
template<typename T, typename = std::true_type>                             \
struct has_member_var_##var_name : std::false_type {};                      \
                                                                            \
template<typename T>                                                        \
struct has_member_var_##var_name<                                           \
    T                                                                       \
    , std::integral_constant<                                               \
        bool, std::is_member_object_pointer<decltype(&T::var_name)>::value  \
    >                                                                       \
> : std::true_type {};

#define MEMB_CHECK_WRAPPER(r, data,  elem) CREATE_MEMBER_VAR_CHECK(elem)


#define CREATE_ENABLE_IF_CLAUSE(var_name)                       \
  class = typename std::enable_if<has_member_var_##var_name<T>::value>::type

#define ENABLE_IF_CLAUSE_WRAPPER(r, data, i, elem)               \
            BOOST_PP_COMMA_IF(i) CREATE_ENABLE_IF_CLAUSE(elem)


#define TO_MEMBER_TEST(member_seq)                                               \
            BOOST_PP_SEQ_FOR_EACH(MEMB_CHECK_WRAPPER, _, member_seq)             \
                                                                                 \
            template < typename T,                                               \
                BOOST_PP_SEQ_FOR_EACH_I(ENABLE_IF_CLAUSE_WRAPPER, _, member_seq) \
            >                                                                    \
            void member_test(const T & )                                         \
            {                                                                    \
                std::cout << "works!!\n\n";                                      \
            }

当我执行以下操作时,一切都会好起来的:

TO_MEMBER_TEST((x)(y)(z))

struct A { int x, y, z; };


int main(int argc, char const *argv[])
{
    A a;
    member_test(a);
}

但是,当我改用 TO_MEMBER_TEST((x)(y)(z)(dummy)) 时,代码将无法编译(按预期),因为 member_test(A&) 不再定义,因为 A.dummy 不存在。编译器会给我类似的东西: 模板参数推导/替换失败:错误:'struct std::enable_if' 中没有名为'type'的类型

我怎么能说“没有会员假人”之类的话。而是(例如使用 static_asserts)?

【问题讨论】:

  • 抱歉,我不得不更新标题。我发现THIS...看起来几乎正确...

标签: c++ c-preprocessor metaprogramming sfinae


【解决方案1】:

嗯,当我真的想要一个带有 static_assert 的特定编译器错误时,实际上不需要 enable_if,所以我想出了这个解决方案:

//Check for member variable with given name.
#define CREATE_MEMBER_VAR_CHECK(var_name)                                   \
                                                                            \
template<typename T, typename = std::true_type>                             \
struct has_member_var_##var_name : std::false_type {};                      \
                                                                            \
template<typename T>                                                        \
struct has_member_var_##var_name<                                           \
    T                                                                       \
    , std::integral_constant<                                               \
        bool, std::is_member_object_pointer<decltype(&T::var_name)>::value  \
    >                                                                       \
> : std::true_type {};

#define MEMB_CHECK_WRAPPER(r, data,  elem) CREATE_MEMBER_VAR_CHECK(elem)


#define MEMBER_ERROR(type_name, var_name) \
    #var_name is not a member of #type_name

#define CHECK_HAS_MEMBER(type_name, var_name)                                   \
        static_assert(has_member_var_##var_name<type_name>::value,              \
                      BOOST_PP_STRINGIZE(MEMBER_ERROR(type_name, var_name)) );

#define CHECK_HAS_MEMBER_WRAPPER(r, data, elem) CHECK_HAS_MEMBER(data, elem)

#define TO_MEMBER_TEST(type, member_seq)                                        \
            BOOST_PP_SEQ_FOR_EACH(MEMB_CHECK_WRAPPER, _, member_seq)            \
            BOOST_PP_SEQ_FOR_EACH(CHECK_HAS_MEMBER_WRAPPER, type, member_seq)   \
                                                                                \
            template < typename type>                                           \
            void member_test(const type & )                                     \
            {                                                                   \
                std::cout << "works!!\n\n";                                     \
            }                                                                   



struct A { int x, y, z; };

TO_MEMBER_TEST(A,(x)(y)(z)(dummy))

将调用 CHECK_HAS_MEMBER() 添加到宏 CREATE_MEMBER_VAR_CHECK 的末尾会使其更加“可读”。

【讨论】:

  • 请对您的问题进行修改。您的这篇文章不是答案
  • 这不是答案吗?
  • “这种方法有什么问题吗?或者有人看到更好的解决方案吗?”那是你的帖子,不是吗?
  • 是的,如果我要编辑问题,那么它会归结为正确的。但是,我实际上在 2 小时后回答了我的问题,我不希望其他人浪费他/她的时间。 (这个网站上的任何答案总是隐含地给出更好解决方案的问题,不是吗?)
  • 哦,好吧,是的,评论系统是隐含的。我已经编辑了尾随的问题,以使这篇文章的意思更清楚。感谢您的回答(这是正确的事情!)
猜你喜欢
  • 2020-01-31
  • 1970-01-01
  • 2011-10-07
  • 1970-01-01
  • 2011-08-21
  • 2015-10-17
  • 2016-02-16
  • 2012-02-17
相关资源
最近更新 更多