c++ - MSVC C++ 编译器限制 - 特征在 CRTP 下不起作用

标签 c++ traits crtp

我对 MSVC 2017 和 2019 有一个关于此限制的问题:我想在编译时知道某个 CRTP 模板“派生”类是否具有特定功能。

我得到这个作为我的类(Class)特征评估:

template <typename T>
class function_exists_trait
{
private:
    template <typename U>
    static auto test_todo(U * u) -> decltype(&U::exists) {}
    static auto test_todo(...) -> std::false_type {}

public:
    static constexpr bool value{ !std::is_same<decltype(test_todo(static_cast<T*>(nullptr))), std::false_type>::value };
};

我用一些简单的类测试了它:

struct t1 { void exists() {} };
struct t2 { void exists() {} };
struct t3 {};
struct t4 : public t1 {};
struct t5 : public t3 {};
struct t6 : public t3 { void exists() {} };

我得到了预期的结果。正如预期的那样,评估给出:1 1 0 1 0 1 这个测试:cout << function_exists_trait<t1>::value << " " << ...

我得到了以下 CRTP 简单实现 (0 1 1 1) 的预期结果:

template <typename t> struct u1 {};
struct crtp1 : public u1<crtp1> { void exists() {} };
template <typename t> struct u2 { void exists() {} };
struct crtp2 : public u2<crtp2> {};

cout << function_exists_trait<u1<int>>::value << " "
     << function_exists_trait<crtp1>::value << " "
     << function_exists_trait<u2<int>>::value << " "
     << function_exists_trait<crtp2>::value << endl;

问题是这样的:当尝试评估 CRTP 基类内部的特征时,没有任何效果,我不明白为什么。

template <typename t> struct u3 { 
    static inline constexpr bool value{ function_exists_trait<t>::value }; 
};
struct crtp3 : public u3<crtp3> { void exists() {} };

template <typename t> struct u4 { 
    void exists() {}
    static inline constexpr bool value{ function_exists_trait<t>::value };
};
struct crtp4 : public u4<crtp4> {};

template <typename t> struct u5 {
    void exists() {}
    static inline constexpr bool value{ function_exists_trait<t>::value };
};
struct crtp5 : public u5<crtp5> {
    void exists() {}
};

下面的代码给出了这个结果:0 0 - 0 0 - 0 0 - 0 0

cout << function_exists_trait<u3<int>>::value << " " << u3<int>::value << " - "
        << function_exists_trait<crtp3>::value << " " << crtp3::value << " - " 
        << function_exists_trait<crtp4>::value << " " << crtp4::value << " - "
        << function_exists_trait<crtp5>::value << " " << crtp5::value << endl;

我发布了这个问题,认为我做错了什么,但它似乎是 MSVC 的问题。感谢 P.W.谁告诉我这似乎是 MSVC 的限制。他向我展示了完全相同的代码在 gcc 下给出了这个结果:0 0 - 1 1 - 1 1 - 1 1

有没有人有任何建议如何解决这个问题。也许 MSVC 有一个明显的解决方案来触发预期的结果。或者只是在 MSVC 下实现相同目标的另一种方法。

最佳答案

正如博格丹所发现的,这是一个可行的替代方案:

template <typename t> struct u6 {
    void exists() {}
    static constexpr bool value() { return function_exists_trait<t>::value; }
};
struct crtp6 : public u6<crtp6> {
    void exists() {}
};

感谢大家!

关于c++ - MSVC C++ 编译器限制 - 特征在 CRTP 下不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56244409/

相关文章:

c++ - 异常(exception)情况。 Try-catch block

c++ - 如何以最有效的方式在已排序的 C++ vector 中查找值?

c++ - 查找算法类

c++ - 使用 typename 参数时,模板参数推导/替换失败

C++ CRTP 类层次结构

c++ - 位移位和赋值

rust - 使用 impl Trait 时如何获得 Deref 强制

struct - 如何使用特征的不同实现实例化相同的结构?

c++ - CRTP:表达式模板的编译器相关问题

c++ - 奇怪的重复模板模式 : double inheritance