【问题标题】:noexcept for different operations with template type inside functionnoexcept 用于函数内部模板类型的不同操作
【发布时间】:2018-05-06 08:11:57
【问题描述】:

我想写一个模板函数foo,对T类型做一些操作,在这个函数里面T类型的值可以是:

  • 已复制
  • 已分配
  • 用运算符+求和

所以,我需要为这个函数指定 noexcept ,但上面已经提到了限制。

这是我的代码,但它不能正常工作:

template<class T>
void foo() 
    noexcept(noexcept(std::declval<T>() + std::declval<T>()) && std::is_copy_constructible<T>::value && std::is_assignable<T, T>::value)
{}

bool b1 = noexcept(foo<int>()); // false, but should return true
bool b2 = noexcept(foo<std::string>()); // false

我应该怎么做才能让它正常工作?

【问题讨论】:

  • “所以,我需要为这个函数指定 noexcept” 我看不到因果关系。为什么不简单地使用 sfinae?
  • @YSC 在这种情况下我不能使用 SFINAE
  • 这仅在 operator+(T,T) 定义为 noexcept 时有效。什么if it's not
  • @YSC 这只是我尝试用这样的operator+定义这个函数,如果你知道解决这个问题的另一种方法,请写在这里
  • 好吧,sfinae 但你说你可以(不被允许?)不可以。

标签: c++ c++11 stl noexcept


【解决方案1】:

noexcept(foo&lt;int&gt;()); 为假,因为std::is_assignable&lt;int, int&gt;::value 为假,例如你不能写1 = 1。您可能想做的是改用std::is_assignable&lt;T&amp;, T&gt;

【讨论】:

    【解决方案2】:

    您尝试使用noexcept() 检查T operator+(T,T) 的存在,但这只会检测到noexcept operator+。在我看来,我们可以做得更好。

    namespace detail
    {
        template<class>
        struct sfinae_true : std::true_type{};
    
        template<class T>
        static auto can_add(int) -> sfinae_true<decltype(std::declval<T>() + std::declval<T>())>;
    
        template<class>
        static auto can_add(long) -> std::false_type;
    }
    template<class T>
    struct can_add : decltype(detail::can_add<T>(0))
    {};
    

    这定义了一个特征来检查对于给定类型T,表达式T{}+T{} 是否有意义。

    测试用例:

    struct s1 {};
    s1 operator+(s1,s1) { return s1{}; }
    
    struct s2 {};
    s2 operator+(s2 const&, s2 const&) { return s2{}; }
    
    struct s3 {};
    
    #include <iostream>
    int main()
    {
        std::cout << can_add<s1>::value << "\n"; // true
        std::cout << can_add<s2>::value << "\n"; // true
        std::cout << can_add<s3>::value << "\n"; // false
    }
    

    然后你可以定义:

    template<class T>
    struct is_foo_compatible : std::conjunction<
        can_add<T>,
        std::is_copy_constructible<T>,
        std::is_assignable<T&, T>
    > {};
    

    它就是有效的™。

    【讨论】:

      【解决方案3】:

      问题在于您的std::is_assignable&lt;int, int&gt;(即false)。您通常不能分配给int,只能分配给int&amp;(即左值引用,这意味着您正在修改的实际对象的存在)。如果没有引用限定符,r 值也必须是可赋值的(例如语句 1=1 必须是有效的)。

      因此,在 std::is_assignable 表达式中将您的 T 更改为 T&amp;

      【讨论】:

        猜你喜欢
        • 2014-06-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-08-05
        • 1970-01-01
        • 2015-01-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多