Return Return Types and Tag Dispatch

Experimenting with return data types and sending tags, I wrote the following code.

#include <string>
#include <iostream>

using namespace std;

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

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;};

class Tester
{
private:
    using t_uint32 = uint32_t;
    using t_string = string;

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);


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

    template<typename t_detail>
    auto access() -> decltype(access(typename Select<t_detail>::choice()));
};

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


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

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



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

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

/*
auto
Tester::access(const Params::t_param2&)
-> decltype(m_param2)
{
return(m_param2);
}
*/

int main() {
auto tester = Tester();
tester.assign<Params::t_param1>(79);
//  tester.assign<Params::t_param2>("viziv");

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;
}

when I compile this code using Apple LLVM version 7.0.2 (clang-700.1.81), I get the following compilation error

junk1.cpp:78:9: error: out-of-line definition of 'access' does not match any declaration in 'Tester'
Tester::access()
        ^~~~~~
1 error generated.

Curiously, when I uncomment the code for assigning and accessing param2 (commented out in the code above), it compiles the penalty and creates the desired result.

What am I doing wrong? Can someone explain to me why including param2 change in compilation behavior?

+4
source share
1 answer

I think that there are one and a half problems.

, . , .

access (Demo); , access , .

, , access - - (, ).

( , ) , access , access ( ADL). , Select<t_detail>::choice , .

, private access Tester (- access2), access ()

0

Source: https://habr.com/ru/post/1629392/


All Articles