Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ SFINAE和模板函数实例化:为什么在启用SFINAE类型的函数参数中使用模板参数时无法推导?_C++_Templates_C++14_Template Argument Deduction - Fatal编程技术网

C++ SFINAE和模板函数实例化:为什么在启用SFINAE类型的函数参数中使用模板参数时无法推导?

C++ SFINAE和模板函数实例化:为什么在启用SFINAE类型的函数参数中使用模板参数时无法推导?,c++,templates,c++14,template-argument-deduction,C++,Templates,C++14,Template Argument Deduction,这几天我在用SFINAE做实验,有些事情让我困惑。为什么在my\u函数的实例化中不能推断my\u type\u a class my_type_a {}; template <typename T> class my_common_type { public: constexpr static const bool valid = false; }; template <> class my_common_type<my_type_a> { pub

这几天我在用SFINAE做实验,有些事情让我困惑。为什么在
my\u函数的实例化中不能推断
my\u type\u a

class my_type_a {};

template <typename T>
class my_common_type {
public:
    constexpr static const bool valid = false;
};

template <>
class my_common_type<my_type_a> {
public:
    constexpr static const bool valid = true;
    using type = my_type_a;
};

template <typename T> using my_common_type_t = typename my_common_type<T>::type;

template <typename T, typename V>
void my_function(my_common_type_t<T> my_cvalue, V my_value) {}

int main(void) {
    my_function(my_type_a(), 1.0);
}
class my_type_a{};
模板
将my_分类为common_类型{
公众:
constexpr static const bool valid=false;
};
模板
将my_分类为common_类型{
公众:
constexpr static const bool valid=true;
使用类型=我的类型;
};
使用my_common_type_t=typename my_common_type::type的模板;
模板
void my_函数(my_common_type_t my_cvalue,V my_value){}
内部主(空){
my_函数(my_type_a(),1.0);
}
G++给了我这个:

/home/flisboac/test-template-template-arg-subst.cpp: In function ‘int main()’:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: error: no matching function for call to ‘my_function(my_type_a, double)’
  my_function(my_type_a(), 1.0);
                              ^
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: candidate: template<class T, class V> void my_function(my_common_type_t<T>, V)
 void my_function(my_common_type_t<T> my_type, V my_value) {}
      ^~~~~~~~~~~
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note:   template argument deduction/substitution failed:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: note:   couldn't deduce template parameter ‘T’
  my_function(my_type_a(), 1.0);
                              ^
/home/flisboac/test-template-template-arg-subst.cpp:在函数“int main()”中:
/home/flisboac/test-template-template-arg-subst.cpp:21:30:错误:没有用于调用“my_函数(my_类型_a,double)”的匹配函数
my_函数(my_type_a(),1.0);
^
/home/flisboac/test-template-template-arg-subst.cpp:18:6:注:候选:模板void my_函数(my_common_type_t,V)
void my_函数(my_common_type_t my_type,V my_value){}
^~~~~~~~~~~
/home/flisboac/test-template-template-arg-subst.cpp:18:6:注意:模板参数推导/替换失败:
/home/flisboac/test-template-template-arg-subst.cpp:21:30:注意:无法推断模板参数“t”
my_函数(my_type_a(),1.0);
^
我所期望的是,当调用
my_函数时,正如我在
main
中所做的那样,
T
将被推断为函数的第一个参数的类型,并且该类型将在函数的实例化中使用。但似乎
my_common\u type\u t
在函数之前被实例化,但即便如此,
my\u cvalue
的类型无论如何也会变成
my\u type\u a
,所以我不明白为什么这不起作用

有没有其他方法可以做到这一点?我应该避免两个(或多个)模板间接级别吗?

< P>,请考虑如下:

template <>
struct my_common_type<int> {
    constexpr static const bool valid = true;
    using type = my_type_a;
};

template <>
struct my_common_type<double> {
    constexpr static const bool valid = true;
    using type = my_type_a;
};

// ...

int main(void) {
    my_function(my_type_a{}, 1.0);
}
T
推导出的是什么<代码>整数
,简单!编译器对这种匹配感到满意。另外,由于
test\u t
不能专门化,
test\u t
只被认为是
某物

此外,这也适用于多个级别的别名:

template<typename T>
using test_t = T;

template<typename T>
using test2_t = test_t<T>;

template<typename T>
void call(test2_t<T>) {}

int main() {
    call(1); // will also work
}
请注意,这也是可行的:

template <typename T>
using my_common_type_t = first_t<T, std::enable_if_t<my_common_type<T>::valid>>;
模板
使用my_common_type_t=第一个\u t;
现在扣款将如期发生

注意,这个技巧只适用于C++14,因为在这种情况下,sfinae(删除的参数)只保证在C++14之后发生

还注意到,您应该使用<代码>结构> <代码>,或者使用<代码>公用:使成员<代码> MyAuxMuyLyType::类型< /代码> Pube,否则GCC将输出伪造错误。

< P>:请考虑:

template <>
struct my_common_type<int> {
    constexpr static const bool valid = true;
    using type = my_type_a;
};

template <>
struct my_common_type<double> {
    constexpr static const bool valid = true;
    using type = my_type_a;
};

// ...

int main(void) {
    my_function(my_type_a{}, 1.0);
}
T
推导出的是什么<代码>整数
,简单!编译器对这种匹配感到满意。另外,由于
test\u t
不能专门化,
test\u t
只被认为是
某物

此外,这也适用于多个级别的别名:

template<typename T>
using test_t = T;

template<typename T>
using test2_t = test_t<T>;

template<typename T>
void call(test2_t<T>) {}

int main() {
    call(1); // will also work
}
请注意,这也是可行的:

template <typename T>
using my_common_type_t = first_t<T, std::enable_if_t<my_common_type<T>::valid>>;
模板
使用my_common_type_t=第一个\u t;
现在扣款将如期发生

注意,这个技巧只适用于C++14,因为在这种情况下,sfinae(删除的参数)只保证在C++14之后发生


还要注意的是,您应该为您的trait使用
struct
,或者使用
public:
将成员
my_common_type::type
公开,否则GCC将输出一个伪错误。

my_common_type::type
中,
T
位于。您希望编译器用每种可能的类型
T
实例化
my_common_type
,希望对于其中一种类型,
my_common_type::type
my_type_a
兼容;或者从事定理证明练习,试图从分析的角度找到这样一种类型。编译器两者都没有。@Igor我知道规则1(来自您提供的链接)肯定与我的示例相匹配。然而,为什么不清楚
T
不一定是
my_type_a
?如果在实例化
my\u函数
之前实例化了
my\u common\u type
,则类型可能是
my\u type\u a
或什么都不是(因此该函数将通过SFINAE消除)。如果它在期间或之后被实例化,编译器将把
my_common_type
的信息作为候选(正因为如此,
T=my_type\u a
),不是吗?“为什么不清楚”这是我所说的定理证明练习。“清楚”在这里的意思是“可以从现有事实中证明”。也许可以,但编译器不需要拥有这种推理引擎。我认为信息可以从调用站点获得。但也许我从错误的角度考虑问题。我想我理解这里的问题,但我很难想出一个明确的答案
my_函数
在参数
my_cvalue
中接收类型为
my_common_type::type
的值,并且
T
不在其他任何地方使用。我传递给函数的是一个值
my\u type\u a
,这是具体的
my_common_type::type
仍然未知,因为
::type
依赖于模板替换,而模板替换又依赖于
T
,这是未知的。在
my_common_type::type
中,
T
处于。您希望编译器用每种可能的类型
T
实例化
my_common_type
,希望对于其中一种类型,
my_common_type::type
my_type_a
兼容;或者从事