在我的天真中,我认为这会编译。唉不行。我正在使用Visual Studio 2017社区完全更新。
namespace basic_problem {
auto msvc_does_not_compile = [] ( auto _string )
-> std::vector< decltype(_string) >
{
return std::vector<decltype(_string)>{};
};
}
编译尝试:
int main(int argc, char* argv[])
{
auto vec = basic_problem::msvc_does_not_compile(std::string{});
return 0 ;
}
制作:
error C2514: 'std::vector<unknown-type,std::allocator<_Ty>>': class has no constructors
1> with
1> [
1> _Ty=unknown-type
1> ]
1> program.cpp(97): note: see declaration of 'std::vector<unknown-
type,std::allocator<_Ty>>'
1> with
1> [
1> _Ty=unknown-type
1> ]
我知道我在这里(也许)已经到了界限。任何想法的人?这在C ++ 17中是否可行?基本上我想在运行时决定返回什么类型。不使用(明显)模板。只是'汽车'和lambdas。
当然C ++不会让我这样做。但即使I use if constexpr
msvc拒绝接球:
auto msvc_does_not_compile_too = [](auto _string )
{
using string_type = decltype(_string);
if constexpr ( std::is_same<string_type, std::string>::value )
return std::vector<std::string> ;
else {
return std::vector<std::wstring>;
}
};
奇怪的是我无法在编译时决定在运行时需要什么类型。使用lambda和auto,即。
谢谢...
答案 0 :(得分:2)
在godbolt.org的编译器浏览器中,我发现MSVC 2017 RTW 19.10.25017 complains about the simplest use of constexpr if
即使有标记/std:c++latest
。但是,an official blog post声称自VS 2017.3 [P2](非RTW)以来对constexpr if
的支持。您应该检查您的MSVC版本是否使用编译标记constexpr if
处理/std:c++latest
的简单用法。
如果使用简单的函数模板(如果需要,可以使用特殊化),使用简单的重载,你想要实现的目标就可以正常工作
。#include <string>
#include <vector>
namespace basic_problem {
auto now_it_works(const std::string&) {
return std::vector<std::string>{};
}
auto now_it_works(const std::wstring&) {
return std::vector<std::wstring>{};
}
}
int main(int argc, char* argv[]) {
auto str = basic_problem::now_it_works(std::string{});
static_assert(std::is_same<
decltype(str), std::vector<std::string>
>{}, "");
auto wstr = basic_problem::now_it_works(std::wstring{});
static_assert(std::is_same<
decltype(wstr), std::vector<std::wstring>
>{}, "");
return 0;
}
作为旁注,工作代码说明您的标题具有误导性:决定返回哪种类型不能在运行时进行。相反,在编译时选择适当的模板实例化(或特化)重载。
答案 1 :(得分:0)
要求:获取表示命令行的向量。对于在WIN 10中可能具有命令行的所有类型的可执行文件执行此操作。
但我不是在这里让人们做我的&#34;家庭作业&#34;我在这里检查我是否正确使用C ++ 17 lambda + auto解决方案。它似乎简单健壮,快速。结果证明它不是使用msvc。
实际用例在MSVC + WIN情况下对全局变量进行操作
#include <stdlib.h>
#define _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY
auto wargv_ = (__wargv);
auto argv_ = (__argv );
auto argc_ = (__argc );
#undef _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY
到目前为止一切顺利。但是我们如何判断wargv_何时为null以及何时argv_为null?似乎wargv_总是为空,但是人们无法确定。
那么我们如何封装解决方案的核心?有一个lambda。实施几乎是微不足道的。没有重载,也没有模板。只是现代的C ++。
auto command_line_data = [&]() {
if ( wargv_ != nullptr ) {
return std::vector<std::wstring>(wargv_, wargv_ + argc_);
}
else {
return std::vector<std::string>(argv_, argv_ + argc_);
}
};
唉msvc无法接受这个......感谢@Julius对gcc,clang,msvc进行编码的比较。
更新 - &#34;简单&#34;和msvc友好解决方案
#include <stdlib.h>
namespace {
#define _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY
const auto wargv_ = (__wargv);
const auto argv_ = (__argv);
const auto argc_ = (__argc);
#undef _CRT_DECLARE_GLOBAL_VARIABLES_DIRECTLY
namespace {
using wvecT = std::vector<std::wstring>;
using nvecT = std::vector<std::string >;
// wargv_ != nullptr
inline auto decide(std::true_type tt) {
return wvecT{ wargv_, wargv_ + argc_ };
}
// wargv_ == nullptr
inline auto decide( bool ft) {
return nvecT{ argv_, argv_ + argc_ };
}
}
auto cli_data = []() {
return decide(
wargv_ != NULL
? std::true_type{}
: false
);
};
} // nspace
我现在没有时间进行比较,但是决定()重载和调用似乎&#34;搞笑&#34;,我想感谢msvc运行时......
我确信这可以进行优化并使其看起来不像特技。但这有效..
VS 15.5更新后(对我来说:2017-12-05)
直到昨天(2017-12-06),这还没有在MSVC下进行编译。但是在VS 15.5更新之后就可以了。
auto msvc_does_compile = [](auto _string)
{
using string_type = decltype(_string);
return std::vector<string_type>{};
};
/*
OK since VS 2017 15.5 update
auto vec1 = msvc_does_compile( std::string{} );
*/
添加显式返回类型仍会像往常一样阻塞MSVC,而不是gcc / clang:
auto msvc_does_not_compile = [](auto _string)
// explicit return type makes msvc not to compile
-> std::vector< decltype(_string) >
{
using string_type = decltype(_string);
return std::vector<string_type>{};
};
即使在IDE编辑器阶段,也会停止一些相同但更简单的事情:
auto msvc_ide_does_not_allow = []( bool wide )
{
if (wide)
return std::vector<std::string>();
return std::vector<std::wstring>();
};
是的,再次说麻烦的gcc / clang对上面的任何一个都没有问题。尝试哪种在线格式你更愿意说服自己...
编辑01FEB2018
我的解决方案是错误的,这是一个特技。这是我们现在可以做的最好的事情:
#pragma once
#include <cstdlib>
#include <vector>
#include <string>
#include <tchar.h>
namespace stwish {
using vector_tstring_type = std::vector<std::basic_string<_TCHAR> >;
namespace {
auto cli_data = []() {
try {
return
vector_tstring_type
{
__targv,
(__targv ?
__targv + __argc :
__targv)
};
}
catch (...) {
throw std::runtime_error(__FUNCSIG__ " failed..." );
}
};
}
}
这是Steve Wishnousky先生(微软)设计的解决方案。谢谢史蒂夫。