2

以下是我编写的用于试验 CRTP 设置中的尾随返回类型的模型代码。

#include <iostream>
#include <memory>
#include <utility>

using namespace std;

struct t_aspect{
    struct t_param1 {};
};

// Generic Selector
template <typename t_detail>
struct Select;

template <>
struct Select<t_aspect::t_param1> {
    using typeof = t_aspect::t_param1;
};

//Base CRTP class
template<typename dclas>
class CrtpB
{
    public:
        template<typename T1>
        auto func1() -> // What should be here?
        {
            return(static_cast<dclas*>(this)->func1<T1>());
        }
};


//Derived CRTP class
class CrtpD : public CrtpB<CrtpD>
{
    private:
        uint32_t param1 = 0;

    private:
        auto func1(const t_aspect::t_param1&) -> uint32_t
        {
            return(param1);
        }

    public:
        static auto create() -> unique_ptr<CrtpB>
        {
            return(unique_ptr<CrtpD>(new CrtpD));
        }

        template<typename T1>
        auto func1() -> decltype(func1(typename Select<T1>::typeof()))
        {
            return(func1(typename Select<T1>::typeof()));
        }
};


int main()
{
    auto crtp = CrtpD::create();
    auto parm = crtp->func1<t_aspect::t_param1>();
    return 0;
}

我需要一些帮助来破译 CrtpB 中 func1 的尾随返回类型。

我试过使用

decltype(static_cast<dclas*>(this)->func1<T1>())

但这不起作用。我还尝试根据Inferring return type of templated member functions in CRTP中找到的解决方案编写帮助函数。

template <typename D, typename T>
struct Helpr {
    typedef decltype(static_cast<D*>(0)->func1<T>()) type;
};

但这也不起作用。

4

1 回答 1

1

dclas当基类被实例化时是一个不完整的类型。你需要做两件事来完成这项工作:

  • 推迟类型的检查,func1<T1>()直到类型完成
  • 在依赖表达式上使用template关键字,以便正确解析模板定义:

我们可以通过添加一个间接层来做到这一点:

namespace detail {
    template <class T, class Func1Arg>
    struct func1_t {
         using type = decltype(std::declval<T>().template func1<Func1Arg>());
    };
};

然后你使用这个特征作为尾随返回类型:

template<typename T1>
auto func1() -> typename detail::func1_t<dclas,T1>::type
{
    return(static_cast<dclas*>(this)->template func1<T1>());
}
于 2016-03-01T11:44:33.570 回答