2017-03-28 42 views
2

有没有办法在编译时确定某个模板函数是否专用?如何检查模板函数是否专用?

例如,假设下面的功能:

template<size_t N> 
void foo(); 

我要测试是否foo<42>是专业。请注意,上面的声明不包含任何默认实现。

我试过SFINAE,但无法找到编译器无法从其声明中推断的函数的条件。

有什么想法?

感谢

+4

嗯,你在哪里和为什么要使用这样的东西?也许你最初的问题的更优雅的解决方案就在那里。 – DeiDei

+0

那么,我不能使用重载和SFINAE,因为我有一个非类型的模板参数。然而,我可以在函数中添加一个未命名的'std :: integral_constant '。但我希望有一个更清洁的解决方案... –

+1

非类型模板参数不会阻止您使用重载或SFINAE。目前还不清楚你为什么要检测这个。 – aschepler

回答

3

有没有在编译时间,以确定是否有一定模板函数专门的方法吗?

带功能...我不这么认为。

但是,如果你创建一个仿函数,你可以添加一个静态const成员(is_specialized,在下面的例子),可以给你这个信息

#include <iostream> 

template <std::size_t N> 
struct foo 
{ 
    static constexpr bool is_specialized { false }; 

    void operator()() const 
    { std::cout << "- generic (" << N << ") foo struct" << std::endl; } 
}; 

template <> 
struct foo<42U> 
{ 
    static constexpr bool is_specialized { true }; 

    void operator()() const 
    { std::cout << "- specialized (42) foo struct" << std::endl; } 
}; 

int main() 
{ 
    foo<17U>()(); // print - generic (17) foo struct 
    foo<42U>()(); // print - specialized (42) foo struct 

    std::cout << foo<17U>::is_specialized << std::endl; // print 0 
    std::cout << foo<42U>::is_specialized << std::endl; // print 1 
} 

---编辑---

继Quentin的建议之后(再次感谢!)我开发了另一个基于函数的解决方案,它使用了一些东西来检测仿函数是泛型的还是专用的,仅在泛型仿函数中添加。在这种情况下,一个类型代替一个bool常量。

template <std::size_t N> 
struct foo 
{ 
    // im_not_specialized is added only in the generic version! 
    using im_not_specialized = void; 

    void operator()() const 
    { std::cout << "- generic (" << N << ") foo struct" << std::endl; } 
}; 

template <> 
struct foo<42U> 
{ 
    void operator()() const 
    { std::cout << "- specialized (42) foo struct" << std::endl; } 
}; 

这种类型可以通过SFINAE使用,我提出了一种基于一个constexprisSpecialized()模板函数的例子(具有辅助功能)

template <typename F> 
constexpr bool isSpecializedHelper 
     (int, typename F::im_not_specialized const * = nullptr) 
{ return false; } 

template <typename F> 
constexpr bool isSpecializedHelper (long) 
{ return true; } 

template <typename F> 
constexpr bool isSpecialized() 
{ return isSpecializedHelper<F>(0); } 

这需要更多一点的工作,但isSpecialized()可重复使用用不同的函子(im_not_specialized类型的基于)

下面是一个完整的工作示例

#include <iostream> 

template <std::size_t N> 
struct foo 
{ 
    // im_not_specialized is added only in the generic version! 
    using im_not_specialized = void; 

    void operator()() const 
    { std::cout << "- generic (" << N << ") foo struct" << std::endl; } 
}; 

template <> 
struct foo<42U> 
{ 
    void operator()() const 
    { std::cout << "- specialized (42) foo struct" << std::endl; } 
}; 

template <typename F> 
constexpr bool isSpecializedHelper 
     (int, typename F::im_not_specialized const * = nullptr) 
{ return false; } 

template <typename F> 
constexpr bool isSpecializedHelper (long) 
{ return true; } 

template <typename F> 
constexpr bool isSpecialized() 
{ return isSpecializedHelper<F>(0); } 

int main() 
{ 
    foo<17U>()(); // print - generic (17) foo struct 
    foo<42U>()(); // print - specialized (42) foo struct 

    constexpr auto isSp17 = isSpecialized<foo<17U>>(); 
    constexpr auto isSp42 = isSpecialized<foo<42U>>(); 

    std::cout << isSp17 << std::endl; // print 0 
    std::cout << isSp42 << std::endl; // print 1 
} 
+3

更进一步:在基本模板中声明一个虚拟'使用im_not_specialized = void;',并稍后检测它。现在用户不需要做任何额外的事情:) – Quentin

+0

@Quentin - 不确定应该将...'im_not_specialized'添加到'is_specialized'还是用来替代它?何时应该使用'im_not_specialized'? – max66

+0

它取代'is_specialized'。然后你可以使用SFINAE来检测你正在查看的'foo '是否包含typedef(然后是来自基本模板)或不是(然后它是专门的)。 – Quentin

相关问题