这是another questionçš„åŽç»è¡ŒåŠ¨ã€‚它指的是åŒæ ·çš„问题(我希望),但使用一个完全ä¸åŒçš„例åæ¥è¯´æ˜Žå®ƒã€‚åŽŸå› æ˜¯åœ¨å‰é¢çš„示例ä¸ï¼Œåªæœ‰å®žéªŒæ€§GCC 4.9å› ç¼–è¯‘å™¨é”™è¯¯è€Œå¤±è´¥ã€‚åœ¨æ¤ç¤ºä¾‹ä¸ï¼ŒClangå’ŒGCC 4.8.1也以ä¸åŒæ–¹å¼å¤±è´¥ï¼šClang产生æ„外结果,GCC 4.8.1报告ä¸åŒçš„错误消æ¯ã€‚
上一个问题的ç”案或多或少地说代ç 是有效的,问题在于GCCçš„å®žéªŒç‰ˆæœ¬ã€‚ä½†è¿™ä¸ªç»“æžœè®©æˆ‘æ›´åŠ æ€€ç–‘ã€‚å‡ ä¸ªæœˆæ¥æˆ‘一直困扰ç€æˆ‘怀疑是相关(或相åŒï¼‰çš„问题,这是我第一次有一个å°çš„具体例åæ¥è¯´æ˜Žã€‚
所以,这是一些代ç 。首先,一些通用代ç å°†SFINAE应用于由å¯å˜å‚数模æ¿åˆ«å元函数F
指定的任æ„测试:
#include <iostream>
using namespace std;
using _true = integral_constant <bool, true>;
using _false = integral_constant <bool, false>;
template <typename T> using pass = _true;
template <template <typename...> class F>
struct test
{
template <typename... A> static _false _(...);
template <typename... A> static pass <F <A...> > _(int);
};
template <template <typename...> class F, typename... A>
using sfinae = decltype(test <F>::template _<A...>(0));
其次,一个特定的测试,检查给定的类是å¦å®šä¹‰äº†ä¸€ä¸ªå为type
的类型:
template <typename T> using type_of = typename T::type;
template <typename T> using has_type = sfinae <type_of, T>;
最åŽï¼Œä¸€ä¸ªä¾‹å:
struct A { using type = double; };
int main()
{
cout << has_type <int>() << ", ";
cout << has_type <A>() << endl;
}
预期结果为0, 1
。 Clang说0, 0
。 GCC 4.8.1说
tst.cpp: In substitution of ‘template<class T> using type_of = typename T::type [with T = A ...]’:
tst.cpp:15:51: required from ‘struct test<type_of>’
tst.cpp:19:67: required by substitution of ‘template<template<class ...> class F, class ... A> using sfinae = decltype (test:: _<A ...>(0)) [with F = type_of; A = {T}]’
tst.cpp:24:58: required from here
tst.cpp:23:56: error: ‘A ...’ is not a class, struct, or union type
template <typename T> using type_of = typename T::type;
^
和GCC 4.9说
tst.cpp:19:67: required by substitution of ‘template<template<class ...> class F, class ... A> using sfinae = decltype (test:: _<A ...>(0)) [with F = type_of; A = {T}]’
tst.cpp:24:58: required from here
tst.cpp:15:51: error: pack expansion argument for non-pack parameter ‘T’ of alias template ‘template<class T> using type_of = typename T::type’
template <typename... A> static pass <F <A...> > _(int);
^
(行å·å¯èƒ½æœ‰æ‰€ä¸åŒï¼‰ã€‚所以,一切都以ä¸åŒçš„æ–¹å¼å¤±è´¥ã€‚
现在,这是一个解决方法。元功能car
从给定包ä¸é€‰æ‹©ç¬¬ä¸€ç§ç±»åž‹ï¼Œç„¶åŽå°†æµ‹è¯•é‡æ–°å®šä¹‰ä¸ºtype_of2
,现在是å¯å˜å‚数:
template <typename... T> struct car_t;
template <typename... T> using car = type_of <car_t <T...> >;
template <typename T, typename... Tn>
struct car_t <T, Tn...> { using type = T; };
template <typename... T> using type_of2 = typename car <T...>::type;
template <typename T> using has_type2 = sfinae <type_of2, T>;
int main()
{
cout << has_type2 <int>() << ", ";
cout << has_type2 <A>() << endl;
}
现在所有三个编译器都按预期说0, 1
。有趣的是,对于任何版本的GCCï¼Œæˆ‘ä»¬å¿…é¡»åˆ é™¤has_type
(å³ä½¿æˆ‘们ä¸ä½¿ç”¨å®ƒï¼‰å¹¶ä¸”åªç•™ä¸‹has_type2
;å¦åˆ™æˆ‘们会有类似的错误。
结æŸï¼šæˆ‘看到一个模æ¿çš„问题需è¦è¡¨å•çš„å¯å˜å‚数模æ¿å‚æ•°
template <typename...> class F
我们实际上将
å½¢å¼çš„éžå˜é‡æ¨¡æ¿åˆ«å作为输入template <typename T> using alias = // ... anything including T or not
并最终调用F
,就好åƒå®ƒæ˜¯variadic:
F <A...>
ç›®å‰çš„æ„è§è®¤ä¸ºè¿™æ˜¯æœ‰æ•ˆçš„,但现在似乎有三个编制者ä¸åŒæ„。所以问题是:是å¦æœ‰æ•ˆï¼Ÿ
对我而言很é‡è¦å› ä¸ºæˆ‘æœ‰å‡ å个现有代ç 文件,基于这个å‡è®¾æ˜¯æœ‰æ•ˆçš„,现在我还需è¦é‡æ–°è®¾è®¡ï¼ˆå› 为这些编译器å˜åœ¨å®žé™…问题),但确切的é‡æ–°è®¾è®¡å°†å–决于回ç”。
ç”案 0 :(得分:2)
è¿™ä¸èƒ½å›žç”上é¢çš„代ç 是å¦æœ‰æ•ˆçš„问题,但这是一个éžå¸¸æ¼‚亮的解决方法,我通过在æ出问题åŽä¸ä¹…进行试验找到了,我觉得分享是有用的。
所需è¦çš„åªæ˜¯ä»¥ä¸‹å®šä¹‰ï¼š
template <template <typename...> class F>
struct temp { };
template <typename... A, template <typename...> class F>
F <A...> subs_fun(temp <F>);
template <template <typename...> class F, typename... A>
using subs = decltype(subs_fun <A...>(temp <F>()));
然åŽï¼Œåªè¦F <A...>
出现问题,请将其替æ¢ä¸ºsubs <F, A...>
ã€‚å°±æ˜¯è¿™æ ·ã€‚æˆ‘æ— æ³•è§£é‡ŠåŽŸå› ï¼Œä½†è¿„ä»Šä¸ºæ¢å®ƒåœ¨æ‰€æœ‰æƒ…况下都有效。
例如,在问题的SFINAE示例ä¸ï¼Œåªéœ€æ›¿æ¢è¡Œ
template <typename... A> static pass <F <A...> > _(int);
通过
template <typename... A> static pass <subs <F, A...> > _(int);
这是仅在一点上的å˜åŒ–,所有剩余的代ç ä¿æŒä¸å˜ã€‚您ä¸éœ€è¦é‡æ–°å®šä¹‰æˆ–包装用作F
çš„æ¯ä¸ªæ¨¡æ¿å…ƒå‡½æ•°ã€‚这是live example。
如果F <A...>
确实有效并且编译器最终支æŒå®ƒï¼Œé‚£ä¹ˆå†æ¬¡è½¬æ¢ä¹Ÿå¾ˆå®¹æ˜“ï¼Œå› ä¸ºæ›´æ”¹å¾ˆå°‘ã€‚
我å‘现这很é‡è¦ï¼Œå› 为它å…许仅用两行指定SFINAE测试
template <typename T> using type_of = typename T::type;
template <typename T> using has_type = sfinae <type_of, T>;
并且完全是通用的。通常,æ¯ä¸ªè¿™æ ·çš„测试需è¦è‡³å°‘10行代ç ,<type_traits>
çš„å®žçŽ°å……æ»¡äº†è¿™æ ·çš„ä»£ç 。在æŸäº›æƒ…况下,æ¤ç±»ä»£ç å—被定义为å®ã€‚使用æ¤è§£å†³æ–¹æ¡ˆï¼Œæ¨¡æ¿å¯ä»¥å®Œæˆå·¥ä½œï¼Œä¸éœ€è¦å®ã€‚
ç”案 1 :(得分:0)
我认为情况已ç»å¾ˆå¥½åœ°æ ‡å‡†åŒ–了; C ++ 11 14.3.3 / 1说:
 Â模æ¿çš„ template-argument template-parameter 应为类模æ¿æˆ–别å模æ¿çš„å称,表示为 id-expression