C++ 无限模板递归,因为没有bool表达式优化,仅使用gcc
我在做一个词法播音员。请参见下面代码中简化的、有问题的部分。该代码使用clang和msvc编译,但无法使用gcc编译。似乎,在lexicalCast的C++ 无限模板递归,因为没有bool表达式优化,仅使用gcc,c++,templates,gcc,sfinae,enable-if,C++,Templates,Gcc,Sfinae,Enable If,我在做一个词法播音员。请参见下面代码中简化的、有问题的部分。该代码使用clang和msvc编译,但无法使用gcc编译。似乎,在lexicalCast的std::enable_的第一个参数中,如果gcc尝试在计算bool表达式之前计算它的所有操作数,而clang和msvc进行优化,并忽略LexicalCastable::value的计算,如果std::is_相同表达式失败。 我的问题是: 标准是否规定了哪些行为是正确的 我如何解决这个问题,才能用GCC编译这段代码 代码: #包括 #包括 模板
std::enable_的第一个参数中,如果
gcc尝试在计算bool表达式之前计算它的所有操作数,而clang和msvc进行优化,并忽略LexicalCastable::value
的计算,如果std::is_相同
表达式失败。
我的问题是:
- 标准是否规定了哪些行为是正确的
- 我如何解决这个问题,才能用GCC编译这段代码
#包括
#包括
模板
类词汇表;
模板类型名
std::启用_if<
!std::值是否相同
&& !std::值是否相同
&&LexicalCastable::value
&&LexicalCastable::value,
至>::键入lexicalCast(const From和From){
返回lexicalCast(lexicalCast(from));
}
模板
类LexicalCastable
{
模板
静态自动测试(int)
->decltype(lexicalCast(std::declval()),std::true_type{});
模板
静态自动测试(…)->std::false_类型;
公众:
静态常量布尔值=decltype(测试(0))::值;
};
静态断言(!LexicalCastable::value,“”);
gcc的错误:
prog.cpp: In substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’:
prog.cpp:35:45: required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3: required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30: required by substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’
prog.cpp:35:45: required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3: required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30: [ skipping 889 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
prog.cpp:35:45: required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3: required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:29:30: required by substitution of ‘template<class TT> static decltype ((lexicalCast<TT>(declval<From>()), std::true_type{})) LexicalCastable<From, To>::test(int) [with TT = std::__cxx11::basic_string<char>]’
prog.cpp:35:45: required from ‘const bool LexicalCastable<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >::value’
prog.cpp:19:3: required by substitution of ‘template<class To, class From> typename std::enable_if<(((((! std::is_constructible<To, From>::value) && (! std::is_same<std::__cxx11::basic_string<char>, To>::value)) && (! std::is_same<std::__cxx11::basic_string<char>, From>::value)) && LexicalCastable<From, std::__cxx11::basic_string<char> >::value) && LexicalCastable<std::__cxx11::basic_string<char>, To>::value), To>::type lexicalCast(const From&) [with To = std::__cxx11::basic_string<char>; From = <missing>]’
prog.cpp:40:43: required from here
prog.cpp:29:49: fatal error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
-> decltype(lexicalCast<TT>(std::declval<From>()), std::true_type{});
~~~~~~~~~~~~~~~~~~^~
prog.cpp:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[使用TT=std::_cxx11::basic_string]:
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[带TT=std::_cxx11::basic_string]时需要”
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:[跳过889实例化上下文,使用-ftemplate backtrace limit=0禁用]
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
prog.cpp:29:30:替换“模板静态decltype((lexicalCast(declval()),std::true_type{}))LexicalCastable::test(int)[带TT=std::_cxx11::basic_string]时需要”
程序cpp:35:45:从“const bool LexicalCastable::value”中需要
prog.cpp:19:3:替换“模板typename std::enable_if::type lexicalCast(const From&)[with To=std::u_cxx11::basic_string;From=]时需要”
进度cpp:40:43:从这里开始需要
prog.cpp:29:49:致命错误:模板实例化深度超过最大值900(使用-ftemplate depth=增加最大值)
->decltype(lexicalCast(std::declval()),std::true_type{});
~~~~~~~~~~~~~~~~~~^~
如何解决这个问题,使之能够用GCC编译此代码
您可以使用保证短路的std::conjunction
(C++17)
template <typename To, typename From>
typename std::enable_if<
std::conjunction<
std::negation<std::is_same<std::string, To>>,
std::negation<std::is_same<std::string, From>>,
LexicalCastable<From, std::string>
LexicalCastable<std::string, To>>::value,
To>::type
lexicalCast(const From &from)
{
return lexicalCast<To>(lexicalCast<std::string>(from));
}
模板
typename std::启用\u如果<
连词<
否定,
否定,
词汇表
LexicalCastable>::值,
至>::键入
lexicalCast(常量自和自)
{
返回lexicalCast(lexicalCast(from));
}
template <typename To, typename From>
typename std::enable_if<
std::conjunction<
std::negation<std::is_same<std::string, To>>,
std::negation<std::is_same<std::string, From>>,
LexicalCastable<From, std::string>
LexicalCastable<std::string, To>>::value,
To>::type
lexicalCast(const From &from)
{
return lexicalCast<To>(lexicalCast<std::string>(from));
}