首页 > 解决方案 > 模板类中非模板成员函数的 requires 子句

问题描述

我有一个简单的模板类A,如果满足某些要求,我想启用一个功能。

解决方案 1 -requires子句

我尝试的第一个解决方案如下:

template <class T>
class A
{
public:
    void a(void) requires (same_as<T, int>)
    {
        std::cout << "a" << std::endl;
    };
};

这很好用,我可以打电话A<int>().a()但不能A<char>().b();。IntelliSense 还正确报告正确识别 Visual Studio 中的使用错误。

然后我尝试将函数定义移到类之外,我在 Visual Studio 中遇到 C2511 编译器错误,而在 GCC 中它工作正常

template <class T>
class A
{
public:
    void a(void) requires (same_as<T, int>);
};

template <class T>
void A<T>::a(void)
requires (same_as<T, int>)
{
    std::cout << "a" << std::endl;
}

您认为我的代码不正确还是 Visual Studio 编译器错误/功能不完整?


解决方案 2 -static_assert

此解决方案在某些情况下有效,但如果您尝试显式模板实例化(例如template class A<char>)当然会导致编译错误,而且 IntelliSense 也无法正确识别不正确的用法

template <class T>
class A
{
public:

    void a(void);
};

template <class T>
void A<T>::a(void)
{
    static_assert(same_as<T, int>);
    std::cout << "a" << std::endl;
}

解决方案 3 -enable_if

(错误的)

template <class T>
class A
{
public:

    template <std::enable_if_t<same_as<T, int>, bool> = true>
    void a(void);
};

template <class T>
template <std::enable_if_t<same_as<T, int>, bool>>
void A<T>::a(void)
{
    std::cout << "a" << std::endl;
}

该解决方案与#2 具有相同的问题,此外,我不希望添加一些乍一看无法理解的模板。


解决方案 4 - 一些奇怪的编译时继承

template <class T>
class A_base { /*common stuff*/ };

template <class T>
class A : public A_base<T>
{
public:
    A_base<T>::A_base;

    /* non-int stuff*/
};

template <>
class A<int> : public A_base<int>
{
public:
    A_base<int>::A_base;

    void a(void) {};
};

这会很好用,但是在某些情况下它可能会变得非常复杂,并且当一堆级别嵌套时调试起来非常不愉快


您有什么建议/更好的解决方案吗?

提前致谢


编辑:

标签: c++visual-studiotemplatesrequirec++20

解决方案


MSVC C++ 功能声明P0734R0 概念可从 VS 2019 16.3 获得。

您是否可能使用 VS 2017,它对 C++20 和 MSVC 的支持不同?


推荐阅读