成员函数中的尾随返回类型

时间:2016-01-18 09:17:14

标签: c++11 trailing-return-type

我正在尝试学习尾随返回类型的概念以及使用标记分派在成员函数重载中使用它的可能性。我写的玩具实现如下:

    #include <string>
    #include <iostream>

    using namespace std;

    // Tags
    namespace Params
    {
            struct t_param1{};
            struct t_param2{};
    };

    // Selectors to choose the appropriate member functions
    template<typename t_detail>
    struct Select;

    template<>
    struct Select<Params::t_param1> {using choice = Params::t_param1;};

    template<>
    struct Select<Params::t_param2> {using choice = Params::t_param2;};

    template<typename t_object>
    class Tester
    {
            private:
                    using t_uint32 = uint32_t;
                    using t_string = string;

            public:
                    template<typename t_detail, typename t_entity>
                    void assign(t_entity&& entity);

                    // There is a compilation problem here
                    template<typename t_detail>
                    auto access() -> decltype(access(typename Select<t_detail>::choice()));

            private:
                    t_uint32 m_param1;
                    t_string m_param2;

            private:
                    template<typename t_entity>
                    void assign(const Params::t_param1&, t_entity&& entity);

                    template<typename t_entity>
                    void assign(const Params::t_param2&, t_entity&& entity);

                    auto access(const Params::t_param1&) -> decltype(m_param1);
                    auto access(const Params::t_param2&) -> decltype(m_param2);
    };

    // Calls the appropriate assign function based on type t_detail
    template<typename t_object>
    template<typename t_detail, typename t_entity>
    void
    Tester<t_object>::assign(t_entity&& entity)
    {
            assign(typename Select<t_detail>::choice(), entity);
    }

    template<typename t_object>
    template<typename t_entity>
    void
    Tester<t_object>::assign(const Params::t_param1&, t_entity&& entity)
    {
            m_param1 = entity;
            cout << "Assigned m_param2 with " << entity << endl;
    }

    template<typename t_object>
    template<typename t_entity>
    void
    Tester<t_object>::assign(const Params::t_param2&, t_entity&& entity)
    {
            m_param2 = entity;
            cout << "Assigned m_param2 with " << entity << endl;
    }

    // Should call the appropriate access function used on type t_detail
    template<typename t_object>
    template<typename t_detail>
    auto
    Tester<t_object>::access()
            -> decltype(access(typename Select<t_detail>::choice()))
    {
            return(access(typename Select<t_detail>::choice()));
    }

    template<typename t_object>
    auto
    Tester<t_object>::access(const Params::t_param1&)
            -> decltype(m_param1)
    {
            return(m_param1);
    }

    template<typename t_object>
    auto
    Tester<t_object>::access(const Params::t_param2&)
            -> decltype(m_param2)
    {
            return(m_param2);
    }

    int main() {
            auto tester = Tester<string>();
            tester.assign<Params::t_param1>(32);
            tester.assign<Params::t_param2>("something");

            auto param1 = tester.access<Params::t_param1>();
            auto param2 = tester.access<Params::t_param2>();

            cout << "Access: param1 = " << param1 << endl;
            cout << "Access: param2 = " << param2 << endl;

            return 0;
    }

这只是一个玩具示例,因为它不是有用的代码。我知道我如何宣布公共访问功能是错误的。但是,我试图弄清楚它是什么,也理​​解为什么编译器会抛出以下错误。

no matching function for call to 'Tester<std::basic_string<char> >::access()'
  auto param1 = tester.access<Params::t_param1>();

1 个答案:

答案 0 :(得分:0)

这是因为您尝试呼叫的access功能在您尝试呼叫时仍然不存在。 (Live version.

#include <string>
#include <iostream>

namespace Params {
    struct t_param1 {};
    struct t_param2 {};
};

template <class t_detail>
struct Select;
template <>
struct Select<Params::t_param1> {
    using type = Params::t_param1;
};
template <>
struct Select<Params::t_param2> {
    using type = Params::t_param2;
};

template <class t_object>
class Tester {
    using t_uint32 = uint32_t;
    using t_string = std::string;
    t_uint32 m_param1;
    t_string m_param2;
    auto access(const Params::t_param1 &) -> decltype(m_param1);
    auto access(const Params::t_param2 &) -> decltype(m_param2);
    template <class t_entity>
    void assign(const Params::t_param1 &, t_entity &&entity);
    template <class t_entity>
    void assign(const Params::t_param2 &, t_entity &&entity);
public:
    template <class t_detail, class t_entity>
    void assign(t_entity&& entity);
    template <class t_detail>
    auto access() -> decltype(access(typename Select<t_detail>::type()));
};

template <class t_object>
template <class t_detail, class t_entity>
void Tester<t_object>::assign(t_entity &&entity) {
    assign(typename Select<t_detail>::type(), entity);
}

template <class t_object>
template <class t_entity>
void Tester<t_object>::assign(const Params::t_param1 &, t_entity &&entity) {
    m_param1 = entity;
    std::cout << "Assigned m_param2 with " << entity << std::endl;
}

template <class t_object>
template <class t_entity>
void Tester<t_object>::assign(const Params::t_param2 &, t_entity &&entity) {
    m_param2 = entity;
    std::cout << "Assigned m_param2 with " << entity << std::endl;
}

template <class t_object>
template <class t_detail>
auto Tester<t_object>::access()
    -> decltype(access(typename Select<t_detail>::type())) {
    return access(typename Select<t_detail>::type());
}

template <class t_object>
auto Tester<t_object>::access(const Params::t_param1 &)
    -> decltype(m_param1) {
    return m_param1;
}

template <class t_object>
auto Tester<t_object>::access(const Params::t_param2 &)
    -> decltype(m_param2) {
    return m_param2;
}

int main() {
    auto tester = Tester<std::string>();
    tester.assign<Params::t_param1>(32);
    tester.assign<Params::t_param2>("something");

    auto param1 = tester.access<Params::t_param1>();
    auto param2 = tester.access<Params::t_param2>();

    std::cout << "Access: param1 = " << param1 << std::endl;
    std::cout << "Access: param2 = " << param2 << std::endl;
}
  

你可以停止用C ++编写,好像是Java吗? :)