Q:

C++ Return Type Deduction Based on Input Parameters

I am creating a "knowledge processor" which can handle multiple forms of data. The forms of data that I am planning to support are textual, visual, and auditory. Each can be represented via TEXT, VISUAL, and AUDIO, respectively. So every "knowledge", or data, is being represented in a structure called "know_t".
#define VISUAL 0
#define AUDIO  1
#define TEXT   2

struct know_t {
    k_type_t type;
    text_k_t text_value;
    visual_k_t visual_value;
    audio_k_t audio_value;
};

k_type_t is a type definition from int. It is used to store the "type" of the data, which can be represented by the #define'd macros at the beginning of the code snippet.
Getting to the point, I am writing a search algorithm for the processor. Each of these types, VISUAL, AUDIO, and TEXT, can be represented by a "prototype" form. For instance, TEXT data can be represented via a std::string. Such prototype forms of a data will be used to search the knowledge database. To enable easy searching, I created a structure called "search_t" to represent the search.
struct search_t {
    k_type_t type;
    visual_t visual_value;
    audio_t audio_value;
    std::string text_value;

    bool operator == (const struct __search_t &in);
};

Now here the structure may look almost exactly the same as the structure above, know_t, they are very different. For instance, while the type "k_type_t" contains the data for a string, such as the definition, std::string is a form of the data used to search. The same goes to all the other forms of data.
I am using C++'s unordered_map to accomplish the search. The ISO C++ standard states that for an unordered_map to work, a hash function and the "==" operator is needed for the key type, search_t in this case. For that, I decided to write a get_value function that returns the prototype value of a search structure. The problem is that as the type of the data changes, the return type changes.
I have written the following code so far, for the == operator, but my compiler (GCC 4.8.1 with -std=c++11) doesn't seem to like it.
#define test(in) in.type == VISUAL ? in.visual_value : \
                 in.type == AUDIO  ? in.audio_value  : \
                 in.type == TEXT   ? in.text_value   : NULL

bool search_t::operator == (const struct search_t &in) {
    auto getval_search = [](const search_t &in) -> decltype(test(in)) {
        if (in.type == __VISUAL__)
            return in.visual_value;
        if (in.type == __AUDIO__)
            return in.audio_value;
        if (in.type == __TEXT__)
            return in.text_value;
    }

    bool equal = (bool)((this->type) == in.type);
    if (!equal)
        return false;

    search_t tmp = *this; // bugfix
    if (getval_search(tmp) == getval_search(in))
        return true;
}

Is there a way to fix this?

A:

Yeah. The easy way to fix it is to write a normal == comparison:
struct search_t { // because C++
    k_type_t type;
    visual_t visual_value;
    audio_t audio_value;
    std::string text_value;

    bool operator == (const search_t& in) const {
        return type == in.type && visual_value == in.visual_value
            && audio_value == in.audio_value && text_value == in.text_value;
    }
}; 

If it's really only type based, then I guess you could do:
bool operator == (const search_t& in) const {
    if (type != in.type) return false;

    switch (type) {
    case __VISUAL__: return visual_value == in.visual_value;
    case __AUDIO__: return audio_value == in.audio_value;
    case __TEXT__: return text_value == in.text_value;
    default: return false; // or something
}

Note that your types are invalid identifiers, per [global.names]:

Each name that contains a double underscore __ or begins with an underscore followed by an uppercase
  letter (2.12) is reserved to the implementation for any use.

Finally, this probably isn't a good data type for storage. Consider using:
using search_t = boost::variant<visual_t, audio_t, std::string>;

