函数模板的 C++ Decltype

标签 c++ templates

我想创建一个重载模板,它运行一个函数 Foo() 如果一个类包含它,否则它什么都不做。

class A
{
public:
    template <typename U>
    void Foo(U& u)
    {
        std::cout << "Has Foo()" << std::endl;
        // Modify u
    }
};

class B
{
    // Does not contain Foo()
};

我一直在尝试这样运行它

template <typename T, typename U>
decltype(std::declval<T>().Foo()) TriggerFoo(T* t, U& u)
{
    t->Foo(u);
}
template <typename T, typename U>
void TriggerFoo(T* t, U& u)
{
    std::cout << "Does not have Foo()" << std::endl;
}

int main()
{
    A a;
    B b;
    U u;     // Some type

    TriggerFoo<A, U>(&a, u);    // I want to print "Has Foo()".
    TriggerFoo<B, U>(&b, u);    // Prints "Does not have Foo()".

    return 0;
}

目前,这两个类都传递给“没有 Foo()”实例化。它编译,但显然它不起作用,这很可能是因为我对 declval 的理解不够好。我也尝试过使用非模板函数,但它仍然不起作用。

任何帮助将不胜感激。

最佳答案

您的方法存在两个基本问题:

decltype(std::declval<T>().Foo())

这永远不会成功解决,因为有问题的 Foo() 总是带有一个参数。这部分应该是:

decltype(std::declval<T>().Foo(std::declval<U &>()))

但是现在你会遇到一个不同的问题:当类实现Foo()时,模板解析会变得不明确。可以使用任何一个模板函数。

因此,您需要另一个间接级别和不同优先级的模板:

#include <iostream>
#include <type_traits>

class A
{
public:
    template <typename U>
    void Foo(U& u)
    {
        std::cout << "Has Foo()" << std::endl;
        // Modify u
    }
};

class B
{
    // Does not contain Foo()
};

template <typename T, typename U, typename Z=decltype(std::declval<T>().Foo(std::declval<U &>()))>
void DoTriggerFoo(T* t, U& u, int dummy)
{
    t->Foo(u);
}

template <typename T, typename U>
void DoTriggerFoo(T* t, U& u, ...)
{
    std::cout << "Does not have Foo()" << std::endl;
}

template <typename T, typename U>
void TriggerFoo(T *t, U &u)
{
    DoTriggerFoo(t, u, 0);
}

class U {};

int main()
{
    A a;
    B b;
    U u;     // Some type

    TriggerFoo<A, U>(&a, u);    // I want to print "Has Foo()".
    TriggerFoo<B, U>(&b, u);    // Prints "Does not have Foo()".

    return 0;
}

gcc 5.3 的结果:

$ ./t
Has Foo()
Does not have Foo()

附言:

std::declval<T &>().Foo(std::declval<U &>())

对于您的实际类(class),这可能会更好。

关于函数模板的 C++ Decltype,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35931350/

相关文章:

用于定义公共(public)变量 static const integer 的 C++ 标准

c++ - 映射文件中成员结构的地址?

asp.net-mvc - 如何在我的 ASP.NET MVC 后端和我的backbone.js 前端之间共享模板?

c++ - 如何轻松地将 C++ 枚举映射到字符串

c++ - 具有模板化基类 : Base<Derived> 的菱形继承(钻石问题)

c++ - 我可以在GCC和Clang中为单个功能启用严格的浮点行为吗?

c# - C++ 等效于 C# Yield?

c++ - MSVC 2012 通过 SFINAE 检测模板函数的模板参数数量

c++ - 是否可以根据模板参数的条件排除模板成员变量?

c++ - Qt - 未发出有关成员更改的 Q_PROPERTY NOTIFY 信号