c – 模板,decltype和非classtypes

我有一个像这样的函数定义

template <typename T>
auto print(T t) -> decltype(t.print()) {
    return t.print();
}

这个想法是参数必须是T类型,并且必须具有print函数.这个打印功能可以返回任何内容,解释了decltype的需要.例如,您可以这样做:

struct Foo
{
    int print()
    {
        return 42;
    }
};

struct Bar
{
    std::string print()
    {
        return "The answer...";
    }
};

...

std::cout << print(Foo()) << std::endl;    
std::cout << print(Bar()) << std::endl;
/* outputs: 
42
The answer...
*/

我读到模板不能进行运行时实例化,并且您可以从类派生类,然后确定它们的类型以查看要使用的模板参数.但是,我如何为非类型类型执行此操作?这个想法是能够:

template <typename T>
T print(T t) {
    return t;
}

同样,但这给了我模糊的过载错误.资格认证不起作用,即打印< Foo>.另一个得到的问题是,如果我有一个类似的仿函数:

struct Foo
{
  virtual int print();
  operator int() const
  {
    return 42;
  }
};

它现在如何决定?

所以我的问题是,是否可以使用模板解决所有这些歧义,或者我是否必须编写一堆冗余代码?

测试

我逐步添加测试,从下面复制/粘贴每个编辑的解决方案.结果如下:

使用以下课程:

struct Foo
{
    int print()
    {
        return 42;
    }

    operator int() const
    {
        return 32;
    }
};

struct Bar
{
    std::string print()
    {
        return "The answer...";
    }

    operator int() const
    {
        return (int)Foo();
    }
};

struct Baz
{
    operator std::string() const
    {
        return std::string("The answer...");
    }
};

以下测试输出:

std::cout << print(Foo()) << std::endl;    
std::cout << print(Bar()) << std::endl;
std::cout << print(42) << std::endl;
std::cout << print((int)Foo()) << std::endl;
std::cout << print("The answer...") << std::endl;
std::cout << print(std::string("The answer...")) << std::endl;
std::cout << print((int)Bar()) << std::endl;
std::cout << print((std::string)Baz()) << std::endl;

两者都正确输出:

42
The answer...
42
32
The answer...
The answer...
32
The answer...

解决方法:

您可以采用以下方法,如果存在这样的成员函数,则在输入上调用print()成员函数,否则它将返回输入本身:

namespace detail
{
    template<typename T, typename = void>
    struct print_helper
    {
        static T print(T t) {
            return t;
        }
    };

    template<typename T>
    struct print_helper<T, decltype(std::declval<T>().print(), (void)0)>
    {
        static auto print(T t) -> decltype(t.print()) {
            return t.print();
        }
    };
}

template<typename T>
auto print(T t) -> decltype(detail::print_helper<T>::print(t))
{
    return detail::print_helper<T>::print(t);
}

这是一个live example.

上一篇:c – auto和delctype(auto)类型推导示例


下一篇:c – 为什么在“自动返回”功能中需要decltype?