2014-02-24 92 views
2

我有一个模板类需要专门用于包含特定typedef的模板参数。所以我需要两个定义,一个是它的typedef,另一个是它没有的。包含typedef的类型专用模板

我的问题是,我不知道如何否定SFINAE。我显然可以消除非特殊参数的特殊情况,但我不知道如何消除特殊参数的默认值。

于是,我就偏特这样的:

struct NormalType { }; 

struct SpecialType { typedef int special; }; 

template <typename T, typename IsSpecial = void> 
struct DetectSpecial { 
    void detected() { std::cout << "Not special...\n"; } 
}; 

template <typename T> 
struct DetectSpecial<T, typename T::special> { 
    void detected() { std::cout << "Special!\n"; } 
}; 

但专业化并不习惯(as SSCCE on ideone)。

我也考虑过使用enable_if,但我没有看到如何将它用于格式良好的格式与非格式良好的表达式而不是真/假。

对于包含特定typedef的类型,定义DetectSpecial的最简单方法是什么?(typedef的值可能是任何东西;它的存在很重要)?

哦,我仍然坚持使用一些C++ 03编译器。无论如何,我认为SFINAE没有任何变化。

+0

这不会起作用,因为'T :: special'不是'void'。当你实例化'DetectSpecial '时,你正在实例化'DetectSpecial ',它与'DetectSpecial '(部分特化)不匹配。 – dyp

回答

2

所需的最小变化是插入在依赖于T::special和产量void专业化(一些表达以匹配默认参数)。例如:

template<class T> 
struct void_alias 
{ 
    typedef void type; 
}; 

template <typename T> 
struct DetectSpecial<T, typename void_alias<typename T::special>::type> { 
    void detected() { std::cout << "Special!\n"; } 
}; 
+0

似乎工作。简单而优雅。谢谢。 –

1

以下可有助于:(C++ 11)https://ideone.com/XISlZ6(C++ 03)https://ideone.com/egKrcL

#include <cstdint> 

template <typename U> 
class has_special 
{ 
private: 
    template<typename T> struct dummy; 
    template<typename T> 
    static std::uint8_t check(dummy<typename T::special>*); 
    template<typename T> static std::uint16_t check(...); 
public: 
    static 
    constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); 
}; 
+0

除了我得到警告,函数模板的默认模板参数是C++ 11扩展,我也需要它在C++ 03编译器中工作。 –

+0

@JanHudec [它有些变化](http://coliru.stacked-crooked.com/a/c9b3964f019b6c80) – dyp

+0

@dyp:很明显我今天有一个心理障碍,因为我没有意识到制作一个简单的技巧指针来获取可以始终构建的东西。 –