【问题标题】:CRTP: How to infer type of member to be used as return type?CRTP:如何推断要用作返回类型的成员类型?
【发布时间】:2018-05-05 10:03:14
【问题描述】:

我想让 CRTP 基方法的返回类型取决于派生中成员的类型,例如:

template <typename C>
struct sum_a_b {
    ??? sum() { return static_cast<C*>(this)->a + static_cast<C*>(this)->b; }
}

template <typename T> struct a_b : sum_a_b<a_b<T>> { T a,b; };

我应该用什么代替???

我尝试了不同的方式来声明返回类型:

template <typename T>
struct base {
    int get_ok() {  
        return static_cast<T*>(this)->value; 
    }
    auto get_invalid() -> decltype(static_cast<T*>(this)->value) {
        return static_cast<T*>(this)->value; 
    }
    typename T::value_type get_incomplete_type_foo() {  
        return static_cast<T*>(this)->value; 
    }
    auto get_incomplete_type_again() -> decltype(T().value) {  
        return static_cast<T*>(this)->value; 
    }
};

struct foo : base<foo> {
        typedef int value_type;
        value_type value;
};

编译的唯一方法是int get_ok,对于其他我得到的方法(get_invalid_cast):

invalid static_cast from type 'base<foo>*' to type 'foo*'
     auto get_invalid() -> decltype(static_cast<T*>(this)->value) {  return static_cast<T*>(this)->value; }
                                    ^

或(其他两个)

invalid use of incomplete type 'struct foo'
     typename T::value_type get_incomplete_type_foo() {  return static_cast<T*>(this)->value; }
                            ^

【问题讨论】:

  • auto 不起作用?
  • @KillzoneKid afaik auto 没有尾随返回类型是> C++11
  • 哦,我明白了,抱歉错过了标签细节

标签: c++ c++11 decltype crtp static-cast


【解决方案1】:

我认为在 c++14 之前唯一可用的解决方法是使用类型特征:

#include <iostream>

template<typename T>
struct Value;

template <typename T>
struct Base
{
    typename Value<T>::type get_value(void)
    {  
        return static_cast<T*>(this)->m_value; 
    }
};

struct Derived;

template<> 
struct Value<Derived>
{
    using type = float;
};

struct Derived: public Base<Derived>
{
    Value<Derived>::type m_value{};
};

int main()
{
    Derived derived{};
    std::cout << derived.get_value() << std::endl;
}

online compiler

如果Derived 类型是模板,那么类型特征特化将如下所示:

template<typename U>
struct Derived;

template<typename U> 
struct Value<Derived<U>>
{
    using type = float;
};

【讨论】:

  • 如果派生的是模板怎么办?我可以转发声明模板然后将Value 专门用于模板化Derived,就像我的第一个示例一样?
猜你喜欢
  • 2013-08-25
  • 1970-01-01
  • 2016-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
相关资源
最近更新 更多