模板参数推导失败

特马里奇

我正在尝试使用标签并对enable_if模板参数实施约束。这是代码:

#include <type_traits>
#include <iostream>

template<typename Type>
struct tag {}; 

struct Atag {}; 
struct Btag {};

template<typename Type, typename Tag>
struct tag_enabled
{
    static_assert(
        std::is_same
        <
            typename tag<Type>::type, 
            Tag 
        >::value, 
        "Error: Type is not tagged with Tag."
    ); 

    typedef typename std::enable_if
    <
        std::is_same
        <
            typename tag<Type>::type, 
            Tag 
        >::value, 
        Type
    >::type type; 
};

template<typename A>
typename tag_enabled<A, Atag>::type
worker(
   typename tag_enabled<A, Atag>::type const & a
)
{
    A result; 

    std::cout << "Atag -> Atag" << std::endl;

    return result; 
}

template<typename A, typename B>
typename tag_enabled<A, Atag>::type
worker(
    typename tag_enabled<B, Btag>::type const & b
)
{
    A result; 

    std::cout << "Btag -> Atag" << std::endl;

    return result; 
}


template<typename A, typename ... Args>
A caller(Args ... args)
{
    return worker<A>(args ...);
}

struct test_a {}; 
struct test_b {}; 

template<>
struct tag<test_a>
{
    typedef Atag type; 
};

template<>
struct tag<test_b>
{
    typedef Btag type;
};

int main(int argc, const char *argv[])
{
    // caller int(int)
    test_a ta1; 
    test_b tb1; 

    auto ta2 = caller<test_a>(ta1); 

    // Why does this fail?  
    auto ta3 = caller<test_a>(tb1);

    return 0;
}

结果是出现以下错误:

test-template.cpp: In instantiation of ‘A caller(Args ...) [with A = test_a; Args = {test_b}]’:
test-template.cpp:90:34:   required from here
test-template.cpp:63:30: error: no matching function for call to ‘worker(test_b&)’
     return worker<A>(args ...);
                              ^
test-template.cpp:63:30: note: candidates are:
test-template.cpp:35:1: note: template<class A> typename tag_enabled<A, Atag>::type worker(const typename tag_enabled<A, Atag>::type&)
 worker(
 ^
test-template.cpp:35:1: note:   template argument deduction/substitution failed:
test-template.cpp:63:30: note:   cannot convert ‘args#0’ (type ‘test_b’) to type ‘const type& {aka const test_a&}’
     return worker<A>(args ...);
                              ^
test-template.cpp:48:1: note: template<class A, class B> typename tag_enabled<A, Atag>::type worker(const typename tag_enabled<B, Btag>::type&)
 worker(
 ^
test-template.cpp:48:1: note:   template argument deduction/substitution failed:
test-template.cpp:63:30: note:   couldn't deduce template parameter ‘B’
     return worker<A>(args ...);

除最后一个错误外,所有错误均应期待并受到欢迎。tag_enabled应确保不会根据模板参数标签实例化功能模板。这个错误例如:

test-template.cpp:35:1: note:   template argument deduction/substitution failed:
    test-template.cpp:63:30: note:   cannot convert ‘args#0’ (type ‘test_b’) to type ‘const type& {aka const test_a&}’
         return worker<A>(args ...);

很棒,因为我希望该函数的推论失败,因为它应该执行映射Atag -> Atag而不是Btag -> Atag如果两参数功能模板可以工作,SFINAE将(至少希望如此)仅删除该功能候选对象。这是我关心的错误,为什么模板参数推导在这里失败:

test-template.cpp:48:1: note:   template argument deduction/substitution failed:
test-template.cpp:63:30: note:   couldn't deduce template parameter ‘B’
     return worker<A>(args ...);

av

编译器可以推断出一种类型的模板的参数,A或者B,与非型模板参数,N从用下面的结构(组成型的模板函数参数Stroustrup的23.5.2,异14.8.2.1):

A
const A
volatile A
A*
A&
A[constant_expression]
type[N]
class_template<A>
class_template<N>
B<A>
A<N>
A<>
A type::*
A A::*
type A::*
A (*)(args)
type (A::*)(args)
A (type::*)(args)
type (type::*)(args_AN)
A (A::*)(args_AN)
type (A::*)(args_AN)
A (type::*)(args_AN)
type (*)(args_AN)

其中args是不允许推导args_AN的参数列表,并且可以通过递归应用上述规则从中确定A或的参数列表N如果不是所有参数都可以这种方式推导出来,则调用是不明确的。

你的构造

typename tag_enabled<B, Btag>::type const &

没有上述形式之一,因此B不能从

template<typename A, typename B>
typename tag_enabled<A, Atag>::type
worker(typename tag_enabled<B, Btag>::type const & b)

B必须明确指定,与std :: forward的情况完全相同不幸的是,这很不方便。有两种方法可以在允许扣除的同时方便使用

template<typename A, typename B, typename = typename std::enable_if <...> >
typename tag_enabled<A, Atag>::type
worker(B const& b)

要么

template<typename A, typename B>
typename tag_enabled<A, Atag, B, Btag>::type
worker(B const& b)

无论哪种方式,您都必须稍微更改设计。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

模板参数推导失败,SFINAE

来自分类Dev

模板参数推导失败,typedef?

来自分类Dev

C ++-模板参数推导/替换失败

来自分类Dev

可变参数宏中的模板推导失败

来自分类Dev

模板推导因已知参数而失败

来自分类Dev

模板参数推导针对const指针失败

来自分类Dev

为什么模板参数推导失败?

来自分类Dev

特征矩阵的“模板参数推导/替换失败”

来自分类Dev

C ++ 17模板参数推导失败

来自分类Dev

C ++可变参数模板推导失败

来自分类Dev

模板参数推导/替换失败-std :: find()

来自分类Dev

`std :: function`模板参数推导/替换失败

来自分类Dev

相关类型:模板参数推导失败

来自分类Dev

模板推导因已知参数而失败

来自分类Dev

std:map作为模板参数的模板推导失败

来自分类Dev

无法实例化模板:模板参数推导/替换失败

来自分类常见问题

约束参数(位集大小)的模板参数推导失败

来自分类Dev

模板参数推导失败,使用函数指针作为参数

来自分类Dev

可变参数模板参数包推导失败

来自分类Dev

约束参数(位集大小)的模板参数推导失败

来自分类Dev

模板推导失败

来自分类Dev

推导模板参数的模板参数

来自分类Dev

我收到“模板参数推导/替换失败:” C ++错误

来自分类Dev

函数采用Eigen :: Tensor-模板参数推导失败

来自分类Dev

vector <string>并找到:模板参数推导/替换失败?

来自分类Dev

具有模板模板参数的C ++函数失败模板参数推导/替换

来自分类Dev

为什么模板参数推导因std :: function回调的可变参数模板参数而失败?

来自分类Dev

模板参数推导顺序

来自分类Dev

模板参数类型推导