在检查子类型时专门化方法模板

时间:2018-09-28 06:21:35

标签: c++ templates variadic-templates sfinae template-specialization

专门用于方法模板,同时还要检查是否存在某些子类型的语法是什么?

// Syntax works fine for functions
template<class T, class... Assertions> void my_function();

template <class list_t, class list_t::value_type>
void my_function() { }

// Doesn't work for methods
class MyClass {
    template<class T, class... Assertions> void my_method();
};

// Commenting out the next two lines results in successful compile
template <class list_t, class list_t::value_type>
void MyClass::my_method() { }

int main() { }

C语给我:

out-of-line definition of 'my_method' does not match any declaration in 'MyClass'

3 个答案:

答案 0 :(得分:0)

您在这里既不擅长模板方法也不擅长函数。您只是在重载免费模板函数,并试图以一种奇怪的方式重载该方法。要使其正常工作,您应该使用标签分发(因为在C ++中无法实现部分功能模板的专业化)或constexpr if(如果编译器支持C ++ 17

答案 1 :(得分:0)

专业化语法如下:

// dummy list_t...
struct list_t
{
   using value_type = int;
};

// standard implementation:
template<class T, class... Assertions>
void my_function() { }

// specialization
template <>
void my_function<list_t, list_t::value_type>() { }

class MyClass
{
    template<class T, class... Assertions>
    void my_method();
};

// standard implementation:
template<class T, class... Assertions>
void MyClass::my_method() { }

// specialisation
template <>
void MyClass::my_method<list_t, list_t::value_type>() { }

答案 2 :(得分:0)

我不清楚您到底想要什么。

如果仅当NULL是其中的类型为my_method()的类/结构时才希望实现T,并且当您使用{{1 }}中没有value_type,建议通过Tvalue_type使用SFINAE。

类似

declval()

如果可以使用C ++ 17代替decltype(),则可以使用template <typename T> auto my_method () -> decltype( std::declval<typename T::value_type>(), void() ) { }

如果您想要一个decltype( std::declval<typename T::value_type>(), void() )带有一个更通用的版本,并且要为其中带有std::void_t<T::value_type>的类/结构提供一个专门的版本,我建议开发一个简单的通用my_method()另一种方法value_type添加一个my_method()

my_method_helper()

,并将int的SFINAE和函数重载与接收template <typename T> void my_method () { my_method_helper<T>(0); } (因此不完全是my_method_helper())的my_method_helper()结合在一起,并为更通用的版本启用

long

,以及一个完全接收int的版本(与template <typename T> void my_method_helper (long) { } 相比,它是首选版本(如果有的话,首选),但仅当int包含long时才启用。 / p>

T

因此,当value_type包含template <typename T> auto my_method_helper (int) -> decltype( std::declval<typename T::value_type>(), void() ) { } 时调用my_method_helper(int),否则调用T

以下是完整的编译示例(方法名称已更改)

value_type

部分关闭的主题:我不明白您所说的“语法对函数正常工作”是什么意思

my_method_helper(long)

您怎么称呼#include <utility> #include <iostream> struct MyClass { template <typename T> auto method_1 () -> decltype( std::declval<typename T::value_type>(), void() ) { std::cout << "method_1 " << std::endl; } template <typename T> auto method_2 (int) -> decltype( std::declval<typename T::value_type>(), void() ) { std::cout << "method_2 specialized" << std::endl; } template <typename T> void method_2 (long) { std::cout << "method_2 generic" << std::endl; } template <typename T> void method_2 () { method_2<T>(0); } }; struct foo { using value_type = int; }; int main() { MyClass mc; mc.method_1<foo>(); // mc.method_1<int>(); // compilation error mc.method_2<foo>(); // call specialized version mc.method_2<int>(); // call generic version }