0

https://stackoverflow.com/a/31860104

#include <iostream>
#include <string>

template<class T>
auto optionalToString(T* obj)
 -> decltype(  obj->toString()  )
{
    return     obj->toString();
}
auto optionalToString(...) -> std::string
{
    return "toString not defined";
}

struct TA
{
    std::string toString() const
    {
        return "Hello";   
    }
};

struct TB
{
};    

Question> Given the proposed solution optionalToString, how I can use it to detect that TA has toString while TB doesn't.

Community
  • 1
  • 1
q0987
  • 34,938
  • 69
  • 242
  • 387

2 Answers2

3

A solution using can_apply from this code:

template<class T>
using toString_result = decltype(std::declval<T>().toString());

template<class T>
constexpr auto has_toString = can_apply<toString_result, T>::value;

Used like this:

struct TA
{
    std::string toString() const
    {
        return "Hello";   
    }
};

struct TB
{
};

int main()
{
    std::cout << has_toString<TA> << '\n';
    std::cout << has_toString<TB> << '\n';
    return 0;
}

DEMO

Community
  • 1
  • 1
O'Neil
  • 3,790
  • 4
  • 16
  • 30
  • The proposed solution looks simple too me. After all those complicate meta code, it doesn't look like a simple solution. – q0987 Apr 18 '17 at 16:15
  • @q0987 It's a generalized solution which can be used for any operation. If you want to stick with yours, and the purpose is the detection, why not returning a boolean? – O'Neil Apr 18 '17 at 16:37
  • I found where the problem is. The online compiler doesn't generate the correct result and I thought the code doesn't work. It was the issue of the compiler instead of code. Thank you – q0987 Apr 18 '17 at 17:48
1

The given solution allows you to always get a string from any object. If it has a toString() member function, this will be used, otherwise, a default string. Usage example, given the above:

TA a;
TB b;
std::cout << "a: " << optionalToString(&a) << '\n';
std::cout << "b: " << optionalToString(&b) << std::endl;

However, you will not get a boolean value whether a or b has a toString() method. If you want that, you need something like the solution proposed by O'Neil.

chtz
  • 17,329
  • 4
  • 26
  • 56